From 477b917c487a49b61a727d6629a27ca81be6951a Mon Sep 17 00:00:00 2001 From: William Summers Date: Wed, 23 Apr 2025 19:59:02 -0500 Subject: [PATCH 01/38] project structure basic --- .gitignore | 49 + bower.json | 12 - jest.config.js | 27 + lib/xmlToJSON.js | 242 -- lib/xmlToJSON.min.js | 1 - package-lock.json | 3848 ++++++++++++++++++++++++ package.json | 39 +- test/SpecRunner.html | 52 - test/assets/test.css | 4 - test/lib/jasmine-1.3.0/MIT.LICENSE | 20 - test/lib/jasmine-1.3.0/jasmine-html.js | 681 ----- test/lib/jasmine-1.3.0/jasmine.css | 82 - test/lib/jasmine-1.3.0/jasmine.js | 2600 ---------------- test/spec/xmlToJSONSpec.js | 115 - 14 files changed, 3940 insertions(+), 3832 deletions(-) create mode 100644 .gitignore delete mode 100644 bower.json create mode 100644 jest.config.js delete mode 100644 lib/xmlToJSON.js delete mode 100644 lib/xmlToJSON.min.js create mode 100644 package-lock.json delete mode 100644 test/SpecRunner.html delete mode 100644 test/assets/test.css delete mode 100644 test/lib/jasmine-1.3.0/MIT.LICENSE delete mode 100644 test/lib/jasmine-1.3.0/jasmine-html.js delete mode 100644 test/lib/jasmine-1.3.0/jasmine.css delete mode 100644 test/lib/jasmine-1.3.0/jasmine.js delete mode 100644 test/spec/xmlToJSONSpec.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..35dd455 --- /dev/null +++ b/.gitignore @@ -0,0 +1,49 @@ +# Node modules +node_modules/ + +# Build output +dist/ +build/ +lib/ +out/ + +# TypeScript cache +*.tsbuildinfo + +# Jest test output +coverage/ +*.log +jest-test-results.json + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Env files +.env +.env.*.local + +# IDEs and editors +.vscode/ +.idea/ +*.sublime-workspace +*.sublime-project + +# MacOS +.DS_Store + +# Windows +Thumbs.db +ehthumbs.db + +# Optional: if using Yarn PnP +.pnp.* +.yarn/cache/ +.yarn/unplugged/ +.yarn/build-state.yml +.yarn/install-state.gz + +# Optional: if using TurboRepo or similar monorepo tools +.turbo/ \ No newline at end of file diff --git a/bower.json b/bower.json deleted file mode 100644 index 34c8a54..0000000 --- a/bower.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "xmltojson", - "version": "1.3.4", - "main": "./lib/xmlToJSON.js", - "dependencies": {}, - "ignore": [ - "*", - "!lib/*", - "!LICENSE", - "!README.md" - ] -} \ No newline at end of file diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..8d28335 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,27 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +export default { + preset: 'ts-jest/presets/default-esm', + testEnvironment: 'node', + extensionsToTreatAsEsm: ['.ts'], + globals: { + 'ts-jest': { + useESM: true + } + }, + moduleNameMapper: { + '^(\.{1,2}/.*)\.js$': '$1' + } + }; + + // src/index.ts + export function greet(name: string): string { + return `Hello, ${name}!`; + } + + // test/index.test.ts + import { greet } from '../src/index.js'; + + test('greet returns the correct message', () => { + expect(greet('World')).toBe('Hello, World!'); + }); + \ No newline at end of file diff --git a/lib/xmlToJSON.js b/lib/xmlToJSON.js deleted file mode 100644 index 229ffca..0000000 --- a/lib/xmlToJSON.js +++ /dev/null @@ -1,242 +0,0 @@ -/* Copyright 2015 William Summers, MetaTribal LLC - * adapted from https://developer.mozilla.org/en-US/docs/JXON - * - * Licensed under the MIT License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/MIT - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @author William Summers - * - */ - -var xmlToJSON = (function () { - - this.version = "1.3.4"; - - var options = { // set up the default options - mergeCDATA: true, // extract cdata and merge with text - grokAttr: true, // convert truthy attributes to boolean, etc - grokText: true, // convert truthy text/attr to boolean, etc - normalize: true, // collapse multiple spaces to single space - xmlns: true, // include namespaces as attribute in output - namespaceKey: '_ns', // tag name for namespace objects - textKey: '_text', // tag name for text nodes - valueKey: '_value', // tag name for attribute values - attrKey: '_attr', // tag for attr groups - cdataKey: '_cdata', // tag for cdata nodes (ignored if mergeCDATA is true) - attrsAsObject: true, // if false, key is used as prefix to name, set prefix to '' to merge children and attrs. - stripAttrPrefix: true, // remove namespace prefixes from attributes - stripElemPrefix: true, // for elements of same name in diff namespaces, you can enable namespaces and access the nskey property - childrenAsArray: true // force children into arrays - }; - - var prefixMatch = new RegExp(/(?!xmlns)^.*:/); - var trimMatch = new RegExp(/^\s+|\s+$/g); - - this.grokType = function (sValue) { - if (/^\s*$/.test(sValue)) { - return null; - } - if (/^(?:true|false)$/i.test(sValue)) { - return sValue.toLowerCase() === "true"; - } - if (isFinite(sValue)) { - return parseFloat(sValue); - } - return sValue; - }; - - this.parseString = function (xmlString, opt) { - return this.parseXML(this.stringToXML(xmlString), opt); - } - - this.parseXML = function (oXMLParent, opt) { - - // initialize options - for (var key in opt) { - options[key] = opt[key]; - } - - var vResult = {}, - nLength = 0, - sCollectedTxt = ""; - - // parse namespace information - if (options.xmlns && oXMLParent.namespaceURI) { - vResult[options.namespaceKey] = oXMLParent.namespaceURI; - } - - // parse attributes - // using attributes property instead of hasAttributes method to support older browsers - if (oXMLParent.attributes && oXMLParent.attributes.length > 0) { - var vAttribs = {}; - - for (nLength; nLength < oXMLParent.attributes.length; nLength++) { - var oAttrib = oXMLParent.attributes.item(nLength); - vContent = {}; - var attribName = ''; - - if (options.stripAttrPrefix) { - attribName = oAttrib.name.replace(prefixMatch, ''); - - } else { - attribName = oAttrib.name; - } - - if (options.grokAttr) { - vContent[options.valueKey] = this.grokType(oAttrib.value.replace(trimMatch, '')); - } else { - vContent[options.valueKey] = oAttrib.value.replace(trimMatch, ''); - } - - if (options.xmlns && oAttrib.namespaceURI) { - vContent[options.namespaceKey] = oAttrib.namespaceURI; - } - - if (options.attrsAsObject) { // attributes with same local name must enable prefixes - vAttribs[attribName] = vContent; - } else { - vResult[options.attrKey + attribName] = vContent; - } - } - - if (options.attrsAsObject) { - vResult[options.attrKey] = vAttribs; - } else { } - } - - // iterate over the children - if (oXMLParent.hasChildNodes()) { - for (var oNode, sProp, vContent, nItem = 0; nItem < oXMLParent.childNodes.length; nItem++) { - oNode = oXMLParent.childNodes.item(nItem); - - if (oNode.nodeType === 4) { - if (options.mergeCDATA) { - sCollectedTxt += oNode.nodeValue; - } else { - if (vResult.hasOwnProperty(options.cdataKey)) { - if (vResult[options.cdataKey].constructor !== Array) { - vResult[options.cdataKey] = [vResult[options.cdataKey]]; - } - vResult[options.cdataKey].push(oNode.nodeValue); - - } else { - if (options.childrenAsArray) { - vResult[options.cdataKey] = []; - vResult[options.cdataKey].push(oNode.nodeValue); - } else { - vResult[options.cdataKey] = oNode.nodeValue; - } - } - } - } /* nodeType is "CDATASection" (4) */ - else if (oNode.nodeType === 3) { - sCollectedTxt += oNode.nodeValue; - } /* nodeType is "Text" (3) */ - else if (oNode.nodeType === 1) { /* nodeType is "Element" (1) */ - - if (nLength === 0) { - vResult = {}; - } - - // using nodeName to support browser (IE) implementation with no 'localName' property - if (options.stripElemPrefix) { - sProp = oNode.nodeName.replace(prefixMatch, ''); - } else { - sProp = oNode.nodeName; - } - - vContent = xmlToJSON.parseXML(oNode); - - if (vResult.hasOwnProperty(sProp)) { - if (vResult[sProp].constructor !== Array) { - vResult[sProp] = [vResult[sProp]]; - } - vResult[sProp].push(vContent); - - } else { - if (options.childrenAsArray) { - vResult[sProp] = []; - vResult[sProp].push(vContent); - } else { - vResult[sProp] = vContent; - } - nLength++; - } - } - } - } else if (!sCollectedTxt) { // no children and no text, return null - if (options.childrenAsArray) { - vResult[options.textKey] = []; - vResult[options.textKey].push(null); - } else { - vResult[options.textKey] = null; - } - } - - if (sCollectedTxt) { - if (options.grokText) { - var value = this.grokType(sCollectedTxt.replace(trimMatch, '')); - if (value !== null && value !== undefined) { - vResult[options.textKey] = value; - } - } else if (options.normalize) { - vResult[options.textKey] = sCollectedTxt.replace(trimMatch, '').replace(/\s+/g, " "); - } else { - vResult[options.textKey] = sCollectedTxt.replace(trimMatch, ''); - } - } - - return vResult; - } - - - // Convert xmlDocument to a string - // Returns null on failure - this.xmlToString = function (xmlDoc) { - try { - var xmlString = xmlDoc.xml ? xmlDoc.xml : (new XMLSerializer()).serializeToString(xmlDoc); - return xmlString; - } catch (err) { - return null; - } - } - - // Convert a string to XML Node Structure - // Returns null on failure - this.stringToXML = function (xmlString) { - try { - var xmlDoc = null; - - if (window.DOMParser) { - - var parser = new DOMParser(); - xmlDoc = parser.parseFromString(xmlString, "text/xml"); - - return xmlDoc; - } else { - xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); - xmlDoc.async = false; - xmlDoc.loadXML(xmlString); - - return xmlDoc; - } - } catch (e) { - return null; - } - } - - return this; -}).call({}); - -if (typeof module != "undefined" && module !== null && module.exports) module.exports = xmlToJSON; -else if (typeof define === "function" && define.amd) define(function () { return xmlToJSON }); diff --git a/lib/xmlToJSON.min.js b/lib/xmlToJSON.min.js deleted file mode 100644 index dd67b74..0000000 --- a/lib/xmlToJSON.min.js +++ /dev/null @@ -1 +0,0 @@ -var xmlToJSON = function () { this.version = "1.3.4"; var e = { mergeCDATA: !0, grokAttr: !0, grokText: !0, normalize: !0, xmlns: !0, namespaceKey: "_ns", textKey: "_text", valueKey: "_value", attrKey: "_attr", cdataKey: "_cdata", attrsAsObject: !0, stripAttrPrefix: !0, stripElemPrefix: !0, childrenAsArray: !0 }, t = new RegExp(/(?!xmlns)^.*:/), r = new RegExp(/^\s+|\s+$/g); return this.grokType = function (e) { return /^\s*$/.test(e) ? null : /^(?:true|false)$/i.test(e) ? "true" === e.toLowerCase() : isFinite(e) ? parseFloat(e) : e }, this.parseString = function (e, t) { return this.parseXML(this.stringToXML(e), t) }, this.parseXML = function (a, n) { for (var s in n) e[s] = n[s]; var l = {}, i = 0, o = ""; if (e.xmlns && a.namespaceURI && (l[e.namespaceKey] = a.namespaceURI), a.attributes && a.attributes.length > 0) { var c = {}; for (i; i < a.attributes.length; i++) { var u = a.attributes.item(i); m = {}; var p = ""; p = e.stripAttrPrefix ? u.name.replace(t, "") : u.name, e.grokAttr ? m[e.valueKey] = this.grokType(u.value.replace(r, "")) : m[e.valueKey] = u.value.replace(r, ""), e.xmlns && u.namespaceURI && (m[e.namespaceKey] = u.namespaceURI), e.attrsAsObject ? c[p] = m : l[e.attrKey + p] = m } e.attrsAsObject && (l[e.attrKey] = c) } if (a.hasChildNodes()) for (var y, d, m, h = 0; h < a.childNodes.length; h++)4 === (y = a.childNodes.item(h)).nodeType ? e.mergeCDATA ? o += y.nodeValue : l.hasOwnProperty(e.cdataKey) ? (l[e.cdataKey].constructor !== Array && (l[e.cdataKey] = [l[e.cdataKey]]), l[e.cdataKey].push(y.nodeValue)) : e.childrenAsArray ? (l[e.cdataKey] = [], l[e.cdataKey].push(y.nodeValue)) : l[e.cdataKey] = y.nodeValue : 3 === y.nodeType ? o += y.nodeValue : 1 === y.nodeType && (0 === i && (l = {}), d = e.stripElemPrefix ? y.nodeName.replace(t, "") : y.nodeName, m = xmlToJSON.parseXML(y), l.hasOwnProperty(d) ? (l[d].constructor !== Array && (l[d] = [l[d]]), l[d].push(m)) : (e.childrenAsArray ? (l[d] = [], l[d].push(m)) : l[d] = m, i++)); else o || (e.childrenAsArray ? (l[e.textKey] = [], l[e.textKey].push(null)) : l[e.textKey] = null); if (o) if (e.grokText) { var x = this.grokType(o.replace(r, "")); null !== x && void 0 !== x && (l[e.textKey] = x) } else e.normalize ? l[e.textKey] = o.replace(r, "").replace(/\s+/g, " ") : l[e.textKey] = o.replace(r, ""); return l }, this.xmlToString = function (e) { try { return e.xml ? e.xml : (new XMLSerializer).serializeToString(e) } catch (e) { return null } }, this.stringToXML = function (e) { try { var t = null; return window.DOMParser ? t = (new DOMParser).parseFromString(e, "text/xml") : (t = new ActiveXObject("Microsoft.XMLDOM"), t.async = !1, t.loadXML(e), t) } catch (e) { return null } }, this }.call({}); "undefined" != typeof module && null !== module && module.exports ? module.exports = xmlToJSON : "function" == typeof define && define.amd && define(function () { return xmlToJSON }); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..19779e6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3848 @@ +{ + "name": "xmltojson", + "version": "3.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "xmltojson", + "version": "3.0.0", + "devDependencies": { + "jest": "^29.6.0", + "ts-jest": "^29.1.1", + "typescript": "^5.3.3" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001715", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", + "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.141", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.141.tgz", + "integrity": "sha512-qS+qH9oqVYc1ooubTiB9l904WVyM6qNYxtOEEGReoZXw3xlqeYdFr5GclNzbkAufWgwWLEPoDi3d9MoRwwIjGw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-jest": { + "version": "29.3.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz", + "integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.1", + "type-fest": "^4.39.1", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", + "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 47251d5..8dc7054 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,21 @@ { "name": "xmltojson", - "version": "1.3.4", - "description": "Configurable, lightweight XML to JSON converter.", - "main": "./lib/xmlToJSON.js", - "directories": { - "test": "test" + "version": "3.0.0", + "description": "A modern ESM library for Node and browser use.", + "type": "module", + "main": "./dist/index.js", + "exports": { + ".": { + "import": "./dist/index.js" + } }, "scripts": { - "test": "open test/SpecRunner.html" + "build": "tsc", + "test": "jest" }, - "repository": { - "type": "git", - "url": "https://github.com/metatribal/xmlToJSON.git" - }, - "keywords": [ - "xml", - "convert", - "transform", - "json" - ], - "author": "metatribal", - "license": "MIT", - "bugs": { - "url": "https://github.com/metatribal/xmlToJSON/issues" - }, - "homepage": "https://github.com/metatribal/xmlToJSON" -} \ No newline at end of file + "devDependencies": { + "jest": "^29.6.0", + "ts-jest": "^29.1.1", + "typescript": "^5.3.3" + } +} diff --git a/test/SpecRunner.html b/test/SpecRunner.html deleted file mode 100644 index e76c255..0000000 --- a/test/SpecRunner.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - Jasmine Spec Runner - - - - - - - - - - - - - - - - - - - - diff --git a/test/assets/test.css b/test/assets/test.css deleted file mode 100644 index 0f1d4d2..0000000 --- a/test/assets/test.css +++ /dev/null @@ -1,4 +0,0 @@ - -div.cssassist { - display: inline; -} \ No newline at end of file diff --git a/test/lib/jasmine-1.3.0/MIT.LICENSE b/test/lib/jasmine-1.3.0/MIT.LICENSE deleted file mode 100644 index 7c435ba..0000000 --- a/test/lib/jasmine-1.3.0/MIT.LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-2011 Pivotal Labs - -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. diff --git a/test/lib/jasmine-1.3.0/jasmine-html.js b/test/lib/jasmine-1.3.0/jasmine-html.js deleted file mode 100644 index 157f7e8..0000000 --- a/test/lib/jasmine-1.3.0/jasmine-html.js +++ /dev/null @@ -1,681 +0,0 @@ -jasmine.HtmlReporterHelpers = {}; - -jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { - el.appendChild(child); - } - } - } - - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; -}; - -jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { - var results = child.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - - return status; -}; - -jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { - var parentDiv = this.dom.summary; - var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; - var parent = child[parentSuite]; - - if (parent) { - if (typeof this.views.suites[parent.id] == 'undefined') { - this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); - } - parentDiv = this.views.suites[parent.id].element; - } - - parentDiv.appendChild(childElement); -}; - - -jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { - for(var fn in jasmine.HtmlReporterHelpers) { - ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; - } -}; - -jasmine.HtmlReporter = function(_doc) { - var self = this; - var doc = _doc || window.document; - - var reporterView; - - var dom = {}; - - // Jasmine Reporter Public Interface - self.logRunningSpecs = false; - - self.reportRunnerStarting = function(runner) { - var specs = runner.specs() || []; - - if (specs.length == 0) { - return; - } - - createReporterDom(runner.env.versionString()); - doc.body.appendChild(dom.reporter); - setExceptionHandling(); - - reporterView = new jasmine.HtmlReporter.ReporterView(dom); - reporterView.addSpecs(specs, self.specFilter); - }; - - self.reportRunnerResults = function(runner) { - reporterView && reporterView.complete(); - }; - - self.reportSuiteResults = function(suite) { - reporterView.suiteComplete(suite); - }; - - self.reportSpecStarting = function(spec) { - if (self.logRunningSpecs) { - self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } - }; - - self.reportSpecResults = function(spec) { - reporterView.specComplete(spec); - }; - - self.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie - } - } - }; - - self.specFilter = function(spec) { - if (!focusedSpecName()) { - return true; - } - - return spec.getFullName().indexOf(focusedSpecName()) === 0; - }; - - return self; - - function focusedSpecName() { - var specName; - - (function memoizeFocusedSpec() { - if (specName) { - return; - } - - var paramMap = []; - var params = jasmine.HtmlReporter.parameters(doc); - - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - specName = paramMap.spec; - })(); - - return specName; - } - - function createReporterDom(version) { - dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, - dom.banner = self.createDom('div', { className: 'banner' }, - self.createDom('span', { className: 'title' }, "Jasmine "), - self.createDom('span', { className: 'version' }, version)), - - dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), - dom.alert = self.createDom('div', {className: 'alert'}, - self.createDom('span', { className: 'exceptions' }, - self.createDom('label', { className: 'label', for: 'no_try_catch' }, 'No try/catch'), - self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))), - dom.results = self.createDom('div', {className: 'results'}, - dom.summary = self.createDom('div', { className: 'summary' }), - dom.details = self.createDom('div', { id: 'details' })) - ); - } - - function noTryCatch() { - return window.location.search.match(/catch=false/); - } - - function searchWithCatch() { - var params = jasmine.HtmlReporter.parameters(window.document); - var removed = false; - var i = 0; - - while (!removed && i < params.length) { - if (params[i].match(/catch=/)) { - params.splice(i, 1); - removed = true; - } - i++; - } - if (jasmine.CATCH_EXCEPTIONS) { - params.push("catch=false"); - } - - return params.join("&"); - } - - function setExceptionHandling() { - var chxCatch = document.getElementById('no_try_catch'); - - if (noTryCatch()) { - chxCatch.setAttribute('checked', true); - jasmine.CATCH_EXCEPTIONS = false; - } - chxCatch.onclick = function() { - window.location.search = searchWithCatch(); - }; - } -}; -jasmine.HtmlReporter.parameters = function(doc) { - var paramStr = doc.location.search.substring(1); - var params = []; - - if (paramStr.length > 0) { - params = paramStr.split('&'); - } - return params; -} -jasmine.HtmlReporter.sectionLink = function(sectionName) { - var link = '?'; - var params = []; - - if (sectionName) { - params.push('spec=' + encodeURIComponent(sectionName)); - } - if (!jasmine.CATCH_EXCEPTIONS) { - params.push("catch=false"); - } - if (params.length > 0) { - link += params.join("&"); - } - - return link; -}; -jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter); -jasmine.HtmlReporter.ReporterView = function(dom) { - this.startedAt = new Date(); - this.runningSpecCount = 0; - this.completeSpecCount = 0; - this.passedCount = 0; - this.failedCount = 0; - this.skippedCount = 0; - - this.createResultsMenu = function() { - this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, - this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), - ' | ', - this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); - - this.summaryMenuItem.onclick = function() { - dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); - }; - - this.detailsMenuItem.onclick = function() { - showDetails(); - }; - }; - - this.addSpecs = function(specs, specFilter) { - this.totalSpecCount = specs.length; - - this.views = { - specs: {}, - suites: {} - }; - - for (var i = 0; i < specs.length; i++) { - var spec = specs[i]; - this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); - if (specFilter(spec)) { - this.runningSpecCount++; - } - } - }; - - this.specComplete = function(spec) { - this.completeSpecCount++; - - if (isUndefined(this.views.specs[spec.id])) { - this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); - } - - var specView = this.views.specs[spec.id]; - - switch (specView.status()) { - case 'passed': - this.passedCount++; - break; - - case 'failed': - this.failedCount++; - break; - - case 'skipped': - this.skippedCount++; - break; - } - - specView.refresh(); - this.refresh(); - }; - - this.suiteComplete = function(suite) { - var suiteView = this.views.suites[suite.id]; - if (isUndefined(suiteView)) { - return; - } - suiteView.refresh(); - }; - - this.refresh = function() { - - if (isUndefined(this.resultsMenu)) { - this.createResultsMenu(); - } - - // currently running UI - if (isUndefined(this.runningAlert)) { - this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" }); - dom.alert.appendChild(this.runningAlert); - } - this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount); - - // skipped specs UI - if (isUndefined(this.skippedAlert)) { - this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" }); - } - - this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; - - if (this.skippedCount === 1 && isDefined(dom.alert)) { - dom.alert.appendChild(this.skippedAlert); - } - - // passing specs UI - if (isUndefined(this.passedAlert)) { - this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" }); - } - this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); - - // failing specs UI - if (isUndefined(this.failedAlert)) { - this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); - } - this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); - - if (this.failedCount === 1 && isDefined(dom.alert)) { - dom.alert.appendChild(this.failedAlert); - dom.alert.appendChild(this.resultsMenu); - } - - // summary info - this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); - this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; - }; - - this.complete = function() { - dom.alert.removeChild(this.runningAlert); - - this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; - - if (this.failedCount === 0) { - dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); - } else { - showDetails(); - } - - dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); - }; - - return this; - - function showDetails() { - if (dom.reporter.className.search(/showDetails/) === -1) { - dom.reporter.className += " showDetails"; - } - } - - function isUndefined(obj) { - return typeof obj === 'undefined'; - } - - function isDefined(obj) { - return !isUndefined(obj); - } - - function specPluralizedFor(count) { - var str = count + " spec"; - if (count > 1) { - str += "s" - } - return str; - } - -}; - -jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); - - -jasmine.HtmlReporter.SpecView = function(spec, dom, views) { - this.spec = spec; - this.dom = dom; - this.views = views; - - this.symbol = this.createDom('li', { className: 'pending' }); - this.dom.symbolSummary.appendChild(this.symbol); - - this.summary = this.createDom('div', { className: 'specSummary' }, - this.createDom('a', { - className: 'description', - href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()), - title: this.spec.getFullName() - }, this.spec.description) - ); - - this.detail = this.createDom('div', { className: 'specDetail' }, - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(this.spec.getFullName()), - title: this.spec.getFullName() - }, this.spec.getFullName()) - ); -}; - -jasmine.HtmlReporter.SpecView.prototype.status = function() { - return this.getSpecStatus(this.spec); -}; - -jasmine.HtmlReporter.SpecView.prototype.refresh = function() { - this.symbol.className = this.status(); - - switch (this.status()) { - case 'skipped': - break; - - case 'passed': - this.appendSummaryToSuiteDiv(); - break; - - case 'failed': - this.appendSummaryToSuiteDiv(); - this.appendFailureDetail(); - break; - } -}; - -jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { - this.summary.className += ' ' + this.status(); - this.appendToSummary(this.spec, this.summary); -}; - -jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { - this.detail.className += ' ' + this.status(); - - var resultItems = this.spec.results().getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); - } - } - } - - if (messagesDiv.childNodes.length > 0) { - this.detail.appendChild(messagesDiv); - this.dom.details.appendChild(this.detail); - } -}; - -jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { - this.suite = suite; - this.dom = dom; - this.views = views; - - this.element = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description) - ); - - this.appendToSummary(this.suite, this.element); -}; - -jasmine.HtmlReporter.SuiteView.prototype.status = function() { - return this.getSpecStatus(this.suite); -}; - -jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { - this.element.className += " " + this.status(); -}; - -jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); - -/* @deprecated Use jasmine.HtmlReporter instead - */ -jasmine.TrivialReporter = function(doc) { - this.document = doc || document; - this.suiteDivs = {}; - this.logRunningSpecs = false; -}; - -jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { el.appendChild(child); } - } - } - - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; -}; - -jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { - var showPassed, showSkipped; - - this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, - this.createDom('div', { className: 'banner' }, - this.createDom('div', { className: 'logo' }, - this.createDom('span', { className: 'title' }, "Jasmine"), - this.createDom('span', { className: 'version' }, runner.env.versionString())), - this.createDom('div', { className: 'options' }, - "Show ", - showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), - showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") - ) - ), - - this.runnerDiv = this.createDom('div', { className: 'runner running' }, - this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), - this.runnerMessageSpan = this.createDom('span', {}, "Running..."), - this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) - ); - - this.document.body.appendChild(this.outerDiv); - - var suites = runner.suites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - var suiteDiv = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), - this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); - this.suiteDivs[suite.id] = suiteDiv; - var parentDiv = this.outerDiv; - if (suite.parentSuite) { - parentDiv = this.suiteDivs[suite.parentSuite.id]; - } - parentDiv.appendChild(suiteDiv); - } - - this.startedAt = new Date(); - - var self = this; - showPassed.onclick = function(evt) { - if (showPassed.checked) { - self.outerDiv.className += ' show-passed'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); - } - }; - - showSkipped.onclick = function(evt) { - if (showSkipped.checked) { - self.outerDiv.className += ' show-skipped'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); - } - }; -}; - -jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { - var results = runner.results(); - var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; - this.runnerDiv.setAttribute("class", className); - //do it twice for IE - this.runnerDiv.setAttribute("className", className); - var specs = runner.specs(); - var specCount = 0; - for (var i = 0; i < specs.length; i++) { - if (this.specFilter(specs[i])) { - specCount++; - } - } - var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); - message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; - this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); - - this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); -}; - -jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { - var results = suite.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.totalCount === 0) { // todo: change this to check results.skipped - status = 'skipped'; - } - this.suiteDivs[suite.id].className += " " + status; -}; - -jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { - if (this.logRunningSpecs) { - this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } -}; - -jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { - var results = spec.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - var specDiv = this.createDom('div', { className: 'spec ' + status }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(spec.getFullName()), - title: spec.getFullName() - }, spec.description)); - - - var resultItems = results.getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); - } - } - } - - if (messagesDiv.childNodes.length > 0) { - specDiv.appendChild(messagesDiv); - } - - this.suiteDivs[spec.suite.id].appendChild(specDiv); -}; - -jasmine.TrivialReporter.prototype.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie - } - } -}; - -jasmine.TrivialReporter.prototype.getLocation = function() { - return this.document.location; -}; - -jasmine.TrivialReporter.prototype.specFilter = function(spec) { - var paramMap = {}; - var params = this.getLocation().search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - if (!paramMap.spec) { - return true; - } - return spec.getFullName().indexOf(paramMap.spec) === 0; -}; diff --git a/test/lib/jasmine-1.3.0/jasmine.css b/test/lib/jasmine-1.3.0/jasmine.css deleted file mode 100644 index 8c008dc..0000000 --- a/test/lib/jasmine-1.3.0/jasmine.css +++ /dev/null @@ -1,82 +0,0 @@ -body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } - -#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } -#HTMLReporter a { text-decoration: none; } -#HTMLReporter a:hover { text-decoration: underline; } -#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } -#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } -#HTMLReporter #jasmine_content { position: fixed; right: 100%; } -#HTMLReporter .version { color: #aaaaaa; } -#HTMLReporter .banner { margin-top: 14px; } -#HTMLReporter .duration { color: #aaaaaa; float: right; } -#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } -#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } -#HTMLReporter .symbolSummary li.passed { font-size: 14px; } -#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } -#HTMLReporter .symbolSummary li.failed { line-height: 9px; } -#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } -#HTMLReporter .symbolSummary li.skipped { font-size: 14px; } -#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; } -#HTMLReporter .symbolSummary li.pending { line-height: 11px; } -#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; } -#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } -#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } -#HTMLReporter .runningAlert { background-color: #666666; } -#HTMLReporter .skippedAlert { background-color: #aaaaaa; } -#HTMLReporter .skippedAlert:first-child { background-color: #333333; } -#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } -#HTMLReporter .passingAlert { background-color: #a6b779; } -#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } -#HTMLReporter .failingAlert { background-color: #cf867e; } -#HTMLReporter .failingAlert:first-child { background-color: #b03911; } -#HTMLReporter .results { margin-top: 14px; } -#HTMLReporter #details { display: none; } -#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } -#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } -#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } -#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } -#HTMLReporter.showDetails .summary { display: none; } -#HTMLReporter.showDetails #details { display: block; } -#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } -#HTMLReporter .summary { margin-top: 14px; } -#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } -#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } -#HTMLReporter .summary .specSummary.failed a { color: #b03911; } -#HTMLReporter .description + .suite { margin-top: 0; } -#HTMLReporter .suite { margin-top: 14px; } -#HTMLReporter .suite a { color: #333333; } -#HTMLReporter #details .specDetail { margin-bottom: 28px; } -#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } -#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } -#HTMLReporter .resultMessage span.result { display: block; } -#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } - -#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } -#TrivialReporter a:visited, #TrivialReporter a { color: #303; } -#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } -#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } -#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } -#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } -#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } -#TrivialReporter .runner.running { background-color: yellow; } -#TrivialReporter .options { text-align: right; font-size: .8em; } -#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } -#TrivialReporter .suite .suite { margin: 5px; } -#TrivialReporter .suite.passed { background-color: #dfd; } -#TrivialReporter .suite.failed { background-color: #fdd; } -#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } -#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } -#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } -#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } -#TrivialReporter .spec.skipped { background-color: #bbb; } -#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } -#TrivialReporter .passed { background-color: #cfc; display: none; } -#TrivialReporter .failed { background-color: #fbb; } -#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } -#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } -#TrivialReporter .resultMessage .mismatch { color: black; } -#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } -#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } -#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } -#TrivialReporter #jasmine_content { position: fixed; right: 100%; } -#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } diff --git a/test/lib/jasmine-1.3.0/jasmine.js b/test/lib/jasmine-1.3.0/jasmine.js deleted file mode 100644 index 5964112..0000000 --- a/test/lib/jasmine-1.3.0/jasmine.js +++ /dev/null @@ -1,2600 +0,0 @@ -var isCommonJS = typeof window == "undefined" && typeof exports == "object"; - -/** - * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. - * - * @namespace - */ -var jasmine = {}; -if (isCommonJS) exports.jasmine = jasmine; -/** - * @private - */ -jasmine.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); -}; - -/** - * Use jasmine.undefined instead of undefined, since undefined is just - * a plain old variable and may be redefined by somebody else. - * - * @private - */ -jasmine.undefined = jasmine.___undefined___; - -/** - * Show diagnostic messages in the console if set to true - * - */ -jasmine.VERBOSE = false; - -/** - * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. - * - */ -jasmine.DEFAULT_UPDATE_INTERVAL = 250; - -/** - * Maximum levels of nesting that will be included when an object is pretty-printed - */ -jasmine.MAX_PRETTY_PRINT_DEPTH = 40; - -/** - * Default timeout interval in milliseconds for waitsFor() blocks. - */ -jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; - -/** - * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite. - * Set to false to let the exception bubble up in the browser. - * - */ -jasmine.CATCH_EXCEPTIONS = true; - -jasmine.getGlobal = function() { - function getGlobal() { - return this; - } - - return getGlobal(); -}; - -/** - * Allows for bound functions to be compared. Internal use only. - * - * @ignore - * @private - * @param base {Object} bound 'this' for the function - * @param name {Function} function to find - */ -jasmine.bindOriginal_ = function(base, name) { - var original = base[name]; - if (original.apply) { - return function() { - return original.apply(base, arguments); - }; - } else { - // IE support - return jasmine.getGlobal()[name]; - } -}; - -jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); -jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); -jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); -jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); - -jasmine.MessageResult = function(values) { - this.type = 'log'; - this.values = values; - this.trace = new Error(); // todo: test better -}; - -jasmine.MessageResult.prototype.toString = function() { - var text = ""; - for (var i = 0; i < this.values.length; i++) { - if (i > 0) text += " "; - if (jasmine.isString_(this.values[i])) { - text += this.values[i]; - } else { - text += jasmine.pp(this.values[i]); - } - } - return text; -}; - -jasmine.ExpectationResult = function(params) { - this.type = 'expect'; - this.matcherName = params.matcherName; - this.passed_ = params.passed; - this.expected = params.expected; - this.actual = params.actual; - this.message = this.passed_ ? 'Passed.' : params.message; - - var trace = (params.trace || new Error(this.message)); - this.trace = this.passed_ ? '' : trace; -}; - -jasmine.ExpectationResult.prototype.toString = function () { - return this.message; -}; - -jasmine.ExpectationResult.prototype.passed = function () { - return this.passed_; -}; - -/** - * Getter for the Jasmine environment. Ensures one gets created - */ -jasmine.getEnv = function() { - var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); - return env; -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isArray_ = function(value) { - return jasmine.isA_("Array", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isString_ = function(value) { - return jasmine.isA_("String", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isNumber_ = function(value) { - return jasmine.isA_("Number", value); -}; - -/** - * @ignore - * @private - * @param {String} typeName - * @param value - * @returns {Boolean} - */ -jasmine.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; -}; - -/** - * Pretty printer for expecations. Takes any object and turns it into a human-readable string. - * - * @param value {Object} an object to be outputted - * @returns {String} - */ -jasmine.pp = function(value) { - var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; -}; - -/** - * Returns true if the object is a DOM Node. - * - * @param {Object} obj object to check - * @returns {Boolean} - */ -jasmine.isDomNode = function(obj) { - return obj.nodeType > 0; -}; - -/** - * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - * - * @example - * // don't care about which function is passed in, as long as it's a function - * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); - * - * @param {Class} clazz - * @returns matchable object of the type clazz - */ -jasmine.any = function(clazz) { - return new jasmine.Matchers.Any(clazz); -}; - -/** - * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the - * attributes on the object. - * - * @example - * // don't care about any other attributes than foo. - * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); - * - * @param sample {Object} sample - * @returns matchable object for the sample - */ -jasmine.objectContaining = function (sample) { - return new jasmine.Matchers.ObjectContaining(sample); -}; - -/** - * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. - * - * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine - * expectation syntax. Spies can be checked if they were called or not and what the calling params were. - * - * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). - * - * Spies are torn down at the end of every spec. - * - * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. - * - * @example - * // a stub - * var myStub = jasmine.createSpy('myStub'); // can be used anywhere - * - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // actual foo.not will not be called, execution stops - * spyOn(foo, 'not'); - - // foo.not spied upon, execution will continue to implementation - * spyOn(foo, 'not').andCallThrough(); - * - * // fake example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // foo.not(val) will return val - * spyOn(foo, 'not').andCallFake(function(value) {return value;}); - * - * // mock example - * foo.not(7 == 7); - * expect(foo.not).toHaveBeenCalled(); - * expect(foo.not).toHaveBeenCalledWith(true); - * - * @constructor - * @see spyOn, jasmine.createSpy, jasmine.createSpyObj - * @param {String} name - */ -jasmine.Spy = function(name) { - /** - * The name of the spy, if provided. - */ - this.identity = name || 'unknown'; - /** - * Is this Object a spy? - */ - this.isSpy = true; - /** - * The actual function this spy stubs. - */ - this.plan = function() { - }; - /** - * Tracking of the most recent call to the spy. - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy.mostRecentCall.args = [1, 2]; - */ - this.mostRecentCall = {}; - - /** - * Holds arguments for each call to the spy, indexed by call count - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy(7, 8); - * mySpy.mostRecentCall.args = [7, 8]; - * mySpy.argsForCall[0] = [1, 2]; - * mySpy.argsForCall[1] = [7, 8]; - */ - this.argsForCall = []; - this.calls = []; -}; - -/** - * Tells a spy to call through to the actual implemenatation. - * - * @example - * var foo = { - * bar: function() { // do some stuff } - * } - * - * // defining a spy on an existing property: foo.bar - * spyOn(foo, 'bar').andCallThrough(); - */ -jasmine.Spy.prototype.andCallThrough = function() { - this.plan = this.originalValue; - return this; -}; - -/** - * For setting the return value of a spy. - * - * @example - * // defining a spy from scratch: foo() returns 'baz' - * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); - * - * // defining a spy on an existing property: foo.bar() returns 'baz' - * spyOn(foo, 'bar').andReturn('baz'); - * - * @param {Object} value - */ -jasmine.Spy.prototype.andReturn = function(value) { - this.plan = function() { - return value; - }; - return this; -}; - -/** - * For throwing an exception when a spy is called. - * - * @example - * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' - * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); - * - * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' - * spyOn(foo, 'bar').andThrow('baz'); - * - * @param {String} exceptionMsg - */ -jasmine.Spy.prototype.andThrow = function(exceptionMsg) { - this.plan = function() { - throw exceptionMsg; - }; - return this; -}; - -/** - * Calls an alternate implementation when a spy is called. - * - * @example - * var baz = function() { - * // do some stuff, return something - * } - * // defining a spy from scratch: foo() calls the function baz - * var foo = jasmine.createSpy('spy on foo').andCall(baz); - * - * // defining a spy on an existing property: foo.bar() calls an anonymnous function - * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); - * - * @param {Function} fakeFunc - */ -jasmine.Spy.prototype.andCallFake = function(fakeFunc) { - this.plan = fakeFunc; - return this; -}; - -/** - * Resets all of a spy's the tracking variables so that it can be used again. - * - * @example - * spyOn(foo, 'bar'); - * - * foo.bar(); - * - * expect(foo.bar.callCount).toEqual(1); - * - * foo.bar.reset(); - * - * expect(foo.bar.callCount).toEqual(0); - */ -jasmine.Spy.prototype.reset = function() { - this.wasCalled = false; - this.callCount = 0; - this.argsForCall = []; - this.calls = []; - this.mostRecentCall = {}; -}; - -jasmine.createSpy = function(name) { - - var spyObj = function() { - spyObj.wasCalled = true; - spyObj.callCount++; - var args = jasmine.util.argsToArray(arguments); - spyObj.mostRecentCall.object = this; - spyObj.mostRecentCall.args = args; - spyObj.argsForCall.push(args); - spyObj.calls.push({object: this, args: args}); - return spyObj.plan.apply(this, arguments); - }; - - var spy = new jasmine.Spy(name); - - for (var prop in spy) { - spyObj[prop] = spy[prop]; - } - - spyObj.reset(); - - return spyObj; -}; - -/** - * Determines whether an object is a spy. - * - * @param {jasmine.Spy|Object} putativeSpy - * @returns {Boolean} - */ -jasmine.isSpy = function(putativeSpy) { - return putativeSpy && putativeSpy.isSpy; -}; - -/** - * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something - * large in one call. - * - * @param {String} baseName name of spy class - * @param {Array} methodNames array of names of methods to make spies - */ -jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { - throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); - } - return obj; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the current spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.log = function() { - var spec = jasmine.getEnv().currentSpec; - spec.log.apply(spec, arguments); -}; - -/** - * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. - * - * @example - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops - * - * @see jasmine.createSpy - * @param obj - * @param methodName - * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods - */ -var spyOn = function(obj, methodName) { - return jasmine.getEnv().currentSpec.spyOn(obj, methodName); -}; -if (isCommonJS) exports.spyOn = spyOn; - -/** - * Creates a Jasmine spec that will be added to the current suite. - * - * // TODO: pending tests - * - * @example - * it('should be true', function() { - * expect(true).toEqual(true); - * }); - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var it = function(desc, func) { - return jasmine.getEnv().it(desc, func); -}; -if (isCommonJS) exports.it = it; - -/** - * Creates a disabled Jasmine spec. - * - * A convenience method that allows existing specs to be disabled temporarily during development. - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var xit = function(desc, func) { - return jasmine.getEnv().xit(desc, func); -}; -if (isCommonJS) exports.xit = xit; - -/** - * Starts a chain for a Jasmine expectation. - * - * It is passed an Object that is the actual value and should chain to one of the many - * jasmine.Matchers functions. - * - * @param {Object} actual Actual value to test against and expected value - * @return {jasmine.Matchers} - */ -var expect = function(actual) { - return jasmine.getEnv().currentSpec.expect(actual); -}; -if (isCommonJS) exports.expect = expect; - -/** - * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. - * - * @param {Function} func Function that defines part of a jasmine spec. - */ -var runs = function(func) { - jasmine.getEnv().currentSpec.runs(func); -}; -if (isCommonJS) exports.runs = runs; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -var waits = function(timeout) { - jasmine.getEnv().currentSpec.waits(timeout); -}; -if (isCommonJS) exports.waits = waits; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); -}; -if (isCommonJS) exports.waitsFor = waitsFor; - -/** - * A function that is called before each spec in a suite. - * - * Used for spec setup, including validating assumptions. - * - * @param {Function} beforeEachFunction - */ -var beforeEach = function(beforeEachFunction) { - jasmine.getEnv().beforeEach(beforeEachFunction); -}; -if (isCommonJS) exports.beforeEach = beforeEach; - -/** - * A function that is called after each spec in a suite. - * - * Used for restoring any state that is hijacked during spec execution. - * - * @param {Function} afterEachFunction - */ -var afterEach = function(afterEachFunction) { - jasmine.getEnv().afterEach(afterEachFunction); -}; -if (isCommonJS) exports.afterEach = afterEach; - -/** - * Defines a suite of specifications. - * - * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared - * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization - * of setup in some tests. - * - * @example - * // TODO: a simple suite - * - * // TODO: a simple suite with a nested describe block - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var describe = function(description, specDefinitions) { - return jasmine.getEnv().describe(description, specDefinitions); -}; -if (isCommonJS) exports.describe = describe; - -/** - * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var xdescribe = function(description, specDefinitions) { - return jasmine.getEnv().xdescribe(description, specDefinitions); -}; -if (isCommonJS) exports.xdescribe = xdescribe; - - -// Provide the XMLHttpRequest class for IE 5.x-6.x: -jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - function tryIt(f) { - try { - return f(); - } catch(e) { - } - return null; - } - - var xhr = tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP"); - }) || - tryIt(function() { - return new ActiveXObject("Microsoft.XMLHTTP"); - }); - - if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); - - return xhr; -} : XMLHttpRequest; -/** - * @namespace - */ -jasmine.util = {}; - -/** - * Declare that a child class inherit it's prototype from the parent class. - * - * @private - * @param {Function} childClass - * @param {Function} parentClass - */ -jasmine.util.inherit = function(childClass, parentClass) { - /** - * @private - */ - var subclass = function() { - }; - subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass(); -}; - -jasmine.util.formatException = function(e) { - var lineNumber; - if (e.line) { - lineNumber = e.line; - } - else if (e.lineNumber) { - lineNumber = e.lineNumber; - } - - var file; - - if (e.sourceURL) { - file = e.sourceURL; - } - else if (e.fileName) { - file = e.fileName; - } - - var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); - - if (file && lineNumber) { - message += ' in ' + file + ' (line ' + lineNumber + ')'; - } - - return message; -}; - -jasmine.util.htmlEscape = function(str) { - if (!str) return str; - return str.replace(/&/g, '&') - .replace(//g, '>'); -}; - -jasmine.util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); - return arrayOfArgs; -}; - -jasmine.util.extend = function(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; -}; - -/** - * Environment for Jasmine - * - * @constructor - */ -jasmine.Env = function() { - this.currentSpec = null; - this.currentSuite = null; - this.currentRunner_ = new jasmine.Runner(this); - - this.reporter = new jasmine.MultiReporter(); - - this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; - this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; - this.lastUpdate = 0; - this.specFilter = function() { - return true; - }; - - this.nextSpecId_ = 0; - this.nextSuiteId_ = 0; - this.equalityTesters_ = []; - - // wrap matchers - this.matchersClass = function() { - jasmine.Matchers.apply(this, arguments); - }; - jasmine.util.inherit(this.matchersClass, jasmine.Matchers); - - jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); -}; - - -jasmine.Env.prototype.setTimeout = jasmine.setTimeout; -jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; -jasmine.Env.prototype.setInterval = jasmine.setInterval; -jasmine.Env.prototype.clearInterval = jasmine.clearInterval; - -/** - * @returns an object containing jasmine version build info, if set. - */ -jasmine.Env.prototype.version = function () { - if (jasmine.version_) { - return jasmine.version_; - } else { - throw new Error('Version not set'); - } -}; - -/** - * @returns string containing jasmine version build info, if set. - */ -jasmine.Env.prototype.versionString = function() { - if (!jasmine.version_) { - return "version unknown"; - } - - var version = this.version(); - var versionString = version.major + "." + version.minor + "." + version.build; - if (version.release_candidate) { - versionString += ".rc" + version.release_candidate; - } - versionString += " revision " + version.revision; - return versionString; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSpecId = function () { - return this.nextSpecId_++; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSuiteId = function () { - return this.nextSuiteId_++; -}; - -/** - * Register a reporter to receive status updates from Jasmine. - * @param {jasmine.Reporter} reporter An object which will receive status updates. - */ -jasmine.Env.prototype.addReporter = function(reporter) { - this.reporter.addReporter(reporter); -}; - -jasmine.Env.prototype.execute = function() { - this.currentRunner_.execute(); -}; - -jasmine.Env.prototype.describe = function(description, specDefinitions) { - var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); - - var parentSuite = this.currentSuite; - if (parentSuite) { - parentSuite.add(suite); - } else { - this.currentRunner_.add(suite); - } - - this.currentSuite = suite; - - var declarationError = null; - try { - specDefinitions.call(suite); - } catch(e) { - declarationError = e; - } - - if (declarationError) { - this.it("encountered a declaration exception", function() { - throw declarationError; - }); - } - - this.currentSuite = parentSuite; - - return suite; -}; - -jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { - if (this.currentSuite) { - this.currentSuite.beforeEach(beforeEachFunction); - } else { - this.currentRunner_.beforeEach(beforeEachFunction); - } -}; - -jasmine.Env.prototype.currentRunner = function () { - return this.currentRunner_; -}; - -jasmine.Env.prototype.afterEach = function(afterEachFunction) { - if (this.currentSuite) { - this.currentSuite.afterEach(afterEachFunction); - } else { - this.currentRunner_.afterEach(afterEachFunction); - } - -}; - -jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { - return { - execute: function() { - } - }; -}; - -jasmine.Env.prototype.it = function(description, func) { - var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.add(spec); - this.currentSpec = spec; - - if (func) { - spec.runs(func); - } - - return spec; -}; - -jasmine.Env.prototype.xit = function(desc, func) { - return { - id: this.nextSpecId(), - runs: function() { - } - }; -}; - -jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) { - if (a.source != b.source) - mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/"); - - if (a.ignoreCase != b.ignoreCase) - mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier"); - - if (a.global != b.global) - mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier"); - - if (a.multiline != b.multiline) - mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier"); - - if (a.sticky != b.sticky) - mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier"); - - return (mismatchValues.length === 0); -}; - -jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { - if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { - return true; - } - - a.__Jasmine_been_here_before__ = b; - b.__Jasmine_been_here_before__ = a; - - var hasKey = function(obj, keyName) { - return obj !== null && obj[keyName] !== jasmine.undefined; - }; - - for (var property in b) { - if (!hasKey(a, property) && hasKey(b, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - } - for (property in a) { - if (!hasKey(b, property) && hasKey(a, property)) { - mismatchKeys.push("expected missing key '" + property + "', but present in actual."); - } - } - for (property in b) { - if (property == '__Jasmine_been_here_before__') continue; - if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); - } - } - - if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { - mismatchValues.push("arrays were not the same length"); - } - - delete a.__Jasmine_been_here_before__; - delete b.__Jasmine_been_here_before__; - return (mismatchKeys.length === 0 && mismatchValues.length === 0); -}; - -jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; - - for (var i = 0; i < this.equalityTesters_.length; i++) { - var equalityTester = this.equalityTesters_[i]; - var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); - if (result !== jasmine.undefined) return result; - } - - if (a === b) return true; - - if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { - return (a == jasmine.undefined && b == jasmine.undefined); - } - - if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { - return a === b; - } - - if (a instanceof Date && b instanceof Date) { - return a.getTime() == b.getTime(); - } - - if (a.jasmineMatches) { - return a.jasmineMatches(b); - } - - if (b.jasmineMatches) { - return b.jasmineMatches(a); - } - - if (a instanceof jasmine.Matchers.ObjectContaining) { - return a.matches(b); - } - - if (b instanceof jasmine.Matchers.ObjectContaining) { - return b.matches(a); - } - - if (jasmine.isString_(a) && jasmine.isString_(b)) { - return (a == b); - } - - if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { - return (a == b); - } - - if (a instanceof RegExp && b instanceof RegExp) { - return this.compareRegExps_(a, b, mismatchKeys, mismatchValues); - } - - if (typeof a === "object" && typeof b === "object") { - return this.compareObjects_(a, b, mismatchKeys, mismatchValues); - } - - //Straight check - return (a === b); -}; - -jasmine.Env.prototype.contains_ = function(haystack, needle) { - if (jasmine.isArray_(haystack)) { - for (var i = 0; i < haystack.length; i++) { - if (this.equals_(haystack[i], needle)) return true; - } - return false; - } - return haystack.indexOf(needle) >= 0; -}; - -jasmine.Env.prototype.addEqualityTester = function(equalityTester) { - this.equalityTesters_.push(equalityTester); -}; -/** No-op base class for Jasmine reporters. - * - * @constructor - */ -jasmine.Reporter = function() { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerResults = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecStarting = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecResults = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.log = function(str) { -}; - -/** - * Blocks are functions with executable code that make up a spec. - * - * @constructor - * @param {jasmine.Env} env - * @param {Function} func - * @param {jasmine.Spec} spec - */ -jasmine.Block = function(env, func, spec) { - this.env = env; - this.func = func; - this.spec = spec; -}; - -jasmine.Block.prototype.execute = function(onComplete) { - if (!jasmine.CATCH_EXCEPTIONS) { - this.func.apply(this.spec); - } - else { - try { - this.func.apply(this.spec); - } catch (e) { - this.spec.fail(e); - } - } - onComplete(); -}; -/** JavaScript API reporter. - * - * @constructor - */ -jasmine.JsApiReporter = function() { - this.started = false; - this.finished = false; - this.suites_ = []; - this.results_ = {}; -}; - -jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { - this.started = true; - var suites = runner.topLevelSuites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - this.suites_.push(this.summarize_(suite)); - } -}; - -jasmine.JsApiReporter.prototype.suites = function() { - return this.suites_; -}; - -jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { - var isSuite = suiteOrSpec instanceof jasmine.Suite; - var summary = { - id: suiteOrSpec.id, - name: suiteOrSpec.description, - type: isSuite ? 'suite' : 'spec', - children: [] - }; - - if (isSuite) { - var children = suiteOrSpec.children(); - for (var i = 0; i < children.length; i++) { - summary.children.push(this.summarize_(children[i])); - } - } - return summary; -}; - -jasmine.JsApiReporter.prototype.results = function() { - return this.results_; -}; - -jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { - return this.results_[specId]; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { - this.finished = true; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { - this.results_[spec.id] = { - messages: spec.results().getItems(), - result: spec.results().failedCount > 0 ? "failed" : "passed" - }; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.log = function(str) { -}; - -jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ - var results = {}; - for (var i = 0; i < specIds.length; i++) { - var specId = specIds[i]; - results[specId] = this.summarizeResult_(this.results_[specId]); - } - return results; -}; - -jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ - var summaryMessages = []; - var messagesLength = result.messages.length; - for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { - var resultMessage = result.messages[messageIndex]; - summaryMessages.push({ - text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, - passed: resultMessage.passed ? resultMessage.passed() : true, - type: resultMessage.type, - message: resultMessage.message, - trace: { - stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined - } - }); - } - - return { - result : result.result, - messages : summaryMessages - }; -}; - -/** - * @constructor - * @param {jasmine.Env} env - * @param actual - * @param {jasmine.Spec} spec - */ -jasmine.Matchers = function(env, actual, spec, opt_isNot) { - this.env = env; - this.actual = actual; - this.spec = spec; - this.isNot = opt_isNot || false; - this.reportWasCalled_ = false; -}; - -// todo: @deprecated as of Jasmine 0.11, remove soon [xw] -jasmine.Matchers.pp = function(str) { - throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); -}; - -// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] -jasmine.Matchers.prototype.report = function(result, failing_message, details) { - throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); -}; - -jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { - for (var methodName in prototype) { - if (methodName == 'report') continue; - var orig = prototype[methodName]; - matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); - } -}; - -jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { - return function() { - var matcherArgs = jasmine.util.argsToArray(arguments); - var result = matcherFunction.apply(this, arguments); - - if (this.isNot) { - result = !result; - } - - if (this.reportWasCalled_) return result; - - var message; - if (!result) { - if (this.message) { - message = this.message.apply(this, arguments); - if (jasmine.isArray_(message)) { - message = message[this.isNot ? 1 : 0]; - } - } else { - var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; - if (matcherArgs.length > 0) { - for (var i = 0; i < matcherArgs.length; i++) { - if (i > 0) message += ","; - message += " " + jasmine.pp(matcherArgs[i]); - } - } - message += "."; - } - } - var expectationResult = new jasmine.ExpectationResult({ - matcherName: matcherName, - passed: result, - expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], - actual: this.actual, - message: message - }); - this.spec.addMatcherResult(expectationResult); - return jasmine.undefined; - }; -}; - - - - -/** - * toBe: compares the actual to the expected using === - * @param expected - */ -jasmine.Matchers.prototype.toBe = function(expected) { - return this.actual === expected; -}; - -/** - * toNotBe: compares the actual to the expected using !== - * @param expected - * @deprecated as of 1.0. Use not.toBe() instead. - */ -jasmine.Matchers.prototype.toNotBe = function(expected) { - return this.actual !== expected; -}; - -/** - * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. - * - * @param expected - */ -jasmine.Matchers.prototype.toEqual = function(expected) { - return this.env.equals_(this.actual, expected); -}; - -/** - * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual - * @param expected - * @deprecated as of 1.0. Use not.toEqual() instead. - */ -jasmine.Matchers.prototype.toNotEqual = function(expected) { - return !this.env.equals_(this.actual, expected); -}; - -/** - * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes - * a pattern or a String. - * - * @param expected - */ -jasmine.Matchers.prototype.toMatch = function(expected) { - return new RegExp(expected).test(this.actual); -}; - -/** - * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch - * @param expected - * @deprecated as of 1.0. Use not.toMatch() instead. - */ -jasmine.Matchers.prototype.toNotMatch = function(expected) { - return !(new RegExp(expected).test(this.actual)); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeDefined = function() { - return (this.actual !== jasmine.undefined); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeUndefined = function() { - return (this.actual === jasmine.undefined); -}; - -/** - * Matcher that compares the actual to null. - */ -jasmine.Matchers.prototype.toBeNull = function() { - return (this.actual === null); -}; - -/** - * Matcher that compares the actual to NaN. - */ -jasmine.Matchers.prototype.toBeNaN = function() { - this.message = function() { - return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ]; - }; - - return (this.actual !== this.actual); -}; - -/** - * Matcher that boolean not-nots the actual. - */ -jasmine.Matchers.prototype.toBeTruthy = function() { - return !!this.actual; -}; - - -/** - * Matcher that boolean nots the actual. - */ -jasmine.Matchers.prototype.toBeFalsy = function() { - return !this.actual; -}; - - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called. - */ -jasmine.Matchers.prototype.toHaveBeenCalled = function() { - if (arguments.length > 0) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to have been called.", - "Expected spy " + this.actual.identity + " not to have been called." - ]; - }; - - return this.actual.wasCalled; -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ -jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was not called. - * - * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead - */ -jasmine.Matchers.prototype.wasNotCalled = function() { - if (arguments.length > 0) { - throw new Error('wasNotCalled does not take arguments'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to not have been called.", - "Expected spy " + this.actual.identity + " to have been called." - ]; - }; - - return !this.actual.wasCalled; -}; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. - * - * @example - * - */ -jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - this.message = function() { - var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."; - var positiveMessage = ""; - if (this.actual.callCount === 0) { - positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called."; - } else { - positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '') - } - return [positiveMessage, invertedMessage]; - }; - - return this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; - -/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasNotCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", - "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" - ]; - }; - - return !this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** - * Matcher that checks that the expected item is an element in the actual Array. - * - * @param {Object} expected - */ -jasmine.Matchers.prototype.toContain = function(expected) { - return this.env.contains_(this.actual, expected); -}; - -/** - * Matcher that checks that the expected item is NOT an element in the actual Array. - * - * @param {Object} expected - * @deprecated as of 1.0. Use not.toContain() instead. - */ -jasmine.Matchers.prototype.toNotContain = function(expected) { - return !this.env.contains_(this.actual, expected); -}; - -jasmine.Matchers.prototype.toBeLessThan = function(expected) { - return this.actual < expected; -}; - -jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { - return this.actual > expected; -}; - -/** - * Matcher that checks that the expected item is equal to the actual item - * up to a given level of decimal precision (default 2). - * - * @param {Number} expected - * @param {Number} precision, as number of decimal places - */ -jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { - if (!(precision === 0)) { - precision = precision || 2; - } - return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2); -}; - -/** - * Matcher that checks that the expected exception was thrown by the actual. - * - * @param {String} [expected] - */ -jasmine.Matchers.prototype.toThrow = function(expected) { - var result = false; - var exception; - if (typeof this.actual != 'function') { - throw new Error('Actual is not a function'); - } - try { - this.actual(); - } catch (e) { - exception = e; - } - if (exception) { - result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); - } - - var not = this.isNot ? "not " : ""; - - this.message = function() { - if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { - return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); - } else { - return "Expected function to throw an exception."; - } - }; - - return result; -}; - -jasmine.Matchers.Any = function(expectedClass) { - this.expectedClass = expectedClass; -}; - -jasmine.Matchers.Any.prototype.jasmineMatches = function(other) { - if (this.expectedClass == String) { - return typeof other == 'string' || other instanceof String; - } - - if (this.expectedClass == Number) { - return typeof other == 'number' || other instanceof Number; - } - - if (this.expectedClass == Function) { - return typeof other == 'function' || other instanceof Function; - } - - if (this.expectedClass == Object) { - return typeof other == 'object'; - } - - return other instanceof this.expectedClass; -}; - -jasmine.Matchers.Any.prototype.jasmineToString = function() { - return ''; -}; - -jasmine.Matchers.ObjectContaining = function (sample) { - this.sample = sample; -}; - -jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; - - var env = jasmine.getEnv(); - - var hasKey = function(obj, keyName) { - return obj != null && obj[keyName] !== jasmine.undefined; - }; - - for (var property in this.sample) { - if (!hasKey(other, property) && hasKey(this.sample, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); - } - } - - return (mismatchKeys.length === 0 && mismatchValues.length === 0); -}; - -jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () { - return ""; -}; -// Mock setTimeout, clearTimeout -// Contributed by Pivotal Computer Systems, www.pivotalsf.com - -jasmine.FakeTimer = function() { - this.reset(); - - var self = this; - self.setTimeout = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); - return self.timeoutsMade; - }; - - self.setInterval = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); - return self.timeoutsMade; - }; - - self.clearTimeout = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - - self.clearInterval = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - -}; - -jasmine.FakeTimer.prototype.reset = function() { - this.timeoutsMade = 0; - this.scheduledFunctions = {}; - this.nowMillis = 0; -}; - -jasmine.FakeTimer.prototype.tick = function(millis) { - var oldMillis = this.nowMillis; - var newMillis = oldMillis + millis; - this.runFunctionsWithinRange(oldMillis, newMillis); - this.nowMillis = newMillis; -}; - -jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { - var scheduledFunc; - var funcsToRun = []; - for (var timeoutKey in this.scheduledFunctions) { - scheduledFunc = this.scheduledFunctions[timeoutKey]; - if (scheduledFunc != jasmine.undefined && - scheduledFunc.runAtMillis >= oldMillis && - scheduledFunc.runAtMillis <= nowMillis) { - funcsToRun.push(scheduledFunc); - this.scheduledFunctions[timeoutKey] = jasmine.undefined; - } - } - - if (funcsToRun.length > 0) { - funcsToRun.sort(function(a, b) { - return a.runAtMillis - b.runAtMillis; - }); - for (var i = 0; i < funcsToRun.length; ++i) { - try { - var funcToRun = funcsToRun[i]; - this.nowMillis = funcToRun.runAtMillis; - funcToRun.funcToCall(); - if (funcToRun.recurring) { - this.scheduleFunction(funcToRun.timeoutKey, - funcToRun.funcToCall, - funcToRun.millis, - true); - } - } catch(e) { - } - } - this.runFunctionsWithinRange(oldMillis, nowMillis); - } -}; - -jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { - this.scheduledFunctions[timeoutKey] = { - runAtMillis: this.nowMillis + millis, - funcToCall: funcToCall, - recurring: recurring, - timeoutKey: timeoutKey, - millis: millis - }; -}; - -/** - * @namespace - */ -jasmine.Clock = { - defaultFakeTimer: new jasmine.FakeTimer(), - - reset: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.reset(); - }, - - tick: function(millis) { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.tick(millis); - }, - - runFunctionsWithinRange: function(oldMillis, nowMillis) { - jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); - }, - - scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { - jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); - }, - - useMock: function() { - if (!jasmine.Clock.isInstalled()) { - var spec = jasmine.getEnv().currentSpec; - spec.after(jasmine.Clock.uninstallMock); - - jasmine.Clock.installMock(); - } - }, - - installMock: function() { - jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; - }, - - uninstallMock: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.installed = jasmine.Clock.real; - }, - - real: { - setTimeout: jasmine.getGlobal().setTimeout, - clearTimeout: jasmine.getGlobal().clearTimeout, - setInterval: jasmine.getGlobal().setInterval, - clearInterval: jasmine.getGlobal().clearInterval - }, - - assertInstalled: function() { - if (!jasmine.Clock.isInstalled()) { - throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); - } - }, - - isInstalled: function() { - return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; - }, - - installed: null -}; -jasmine.Clock.installed = jasmine.Clock.real; - -//else for IE support -jasmine.getGlobal().setTimeout = function(funcToCall, millis) { - if (jasmine.Clock.installed.setTimeout.apply) { - return jasmine.Clock.installed.setTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.setTimeout(funcToCall, millis); - } -}; - -jasmine.getGlobal().setInterval = function(funcToCall, millis) { - if (jasmine.Clock.installed.setInterval.apply) { - return jasmine.Clock.installed.setInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.setInterval(funcToCall, millis); - } -}; - -jasmine.getGlobal().clearTimeout = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearTimeout(timeoutKey); - } -}; - -jasmine.getGlobal().clearInterval = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearInterval(timeoutKey); - } -}; - -/** - * @constructor - */ -jasmine.MultiReporter = function() { - this.subReporters_ = []; -}; -jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); - -jasmine.MultiReporter.prototype.addReporter = function(reporter) { - this.subReporters_.push(reporter); -}; - -(function() { - var functionNames = [ - "reportRunnerStarting", - "reportRunnerResults", - "reportSuiteResults", - "reportSpecStarting", - "reportSpecResults", - "log" - ]; - for (var i = 0; i < functionNames.length; i++) { - var functionName = functionNames[i]; - jasmine.MultiReporter.prototype[functionName] = (function(functionName) { - return function() { - for (var j = 0; j < this.subReporters_.length; j++) { - var subReporter = this.subReporters_[j]; - if (subReporter[functionName]) { - subReporter[functionName].apply(subReporter, arguments); - } - } - }; - })(functionName); - } -})(); -/** - * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults - * - * @constructor - */ -jasmine.NestedResults = function() { - /** - * The total count of results - */ - this.totalCount = 0; - /** - * Number of passed results - */ - this.passedCount = 0; - /** - * Number of failed results - */ - this.failedCount = 0; - /** - * Was this suite/spec skipped? - */ - this.skipped = false; - /** - * @ignore - */ - this.items_ = []; -}; - -/** - * Roll up the result counts. - * - * @param result - */ -jasmine.NestedResults.prototype.rollupCounts = function(result) { - this.totalCount += result.totalCount; - this.passedCount += result.passedCount; - this.failedCount += result.failedCount; -}; - -/** - * Adds a log message. - * @param values Array of message parts which will be concatenated later. - */ -jasmine.NestedResults.prototype.log = function(values) { - this.items_.push(new jasmine.MessageResult(values)); -}; - -/** - * Getter for the results: message & results. - */ -jasmine.NestedResults.prototype.getItems = function() { - return this.items_; -}; - -/** - * Adds a result, tracking counts (total, passed, & failed) - * @param {jasmine.ExpectationResult|jasmine.NestedResults} result - */ -jasmine.NestedResults.prototype.addResult = function(result) { - if (result.type != 'log') { - if (result.items_) { - this.rollupCounts(result); - } else { - this.totalCount++; - if (result.passed()) { - this.passedCount++; - } else { - this.failedCount++; - } - } - } - this.items_.push(result); -}; - -/** - * @returns {Boolean} True if everything below passed - */ -jasmine.NestedResults.prototype.passed = function() { - return this.passedCount === this.totalCount; -}; -/** - * Base class for pretty printing for expectation results. - */ -jasmine.PrettyPrinter = function() { - this.ppNestLevel_ = 0; -}; - -/** - * Formats a value in a nice, human-readable string. - * - * @param value - */ -jasmine.PrettyPrinter.prototype.format = function(value) { - this.ppNestLevel_++; - try { - if (value === jasmine.undefined) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === jasmine.getGlobal()) { - this.emitScalar(''); - } else if (value.jasmineToString) { - this.emitScalar(value.jasmineToString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (jasmine.isSpy(value)) { - this.emitScalar("spy on " + value.identity); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (value.__Jasmine_been_here_before__) { - this.emitScalar(''); - } else if (jasmine.isArray_(value) || typeof value == 'object') { - value.__Jasmine_been_here_before__ = true; - if (jasmine.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); - } - delete value.__Jasmine_been_here_before__; - } else { - this.emitScalar(value.toString()); - } - } finally { - this.ppNestLevel_--; - } -}; - -jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (!obj.hasOwnProperty(property)) continue; - if (property == '__Jasmine_been_here_before__') continue; - fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && - obj.__lookupGetter__(property) !== null) : false); - } -}; - -jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; - -jasmine.StringPrettyPrinter = function() { - jasmine.PrettyPrinter.call(this); - - this.string = ''; -}; -jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); - -jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); -}; - -jasmine.StringPrettyPrinter.prototype.emitString = function(value) { - this.append("'" + value + "'"); -}; - -jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { - if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { - this.append("Array"); - return; - } - - this.append('[ '); - for (var i = 0; i < array.length; i++) { - if (i > 0) { - this.append(', '); - } - this.format(array[i]); - } - this.append(' ]'); -}; - -jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { - if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { - this.append("Object"); - return; - } - - var self = this; - this.append('{ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.append(property); - self.append(' : '); - if (isGetter) { - self.append(''); - } else { - self.format(obj[property]); - } - }); - - this.append(' }'); -}; - -jasmine.StringPrettyPrinter.prototype.append = function(value) { - this.string += value; -}; -jasmine.Queue = function(env) { - this.env = env; - - // parallel to blocks. each true value in this array means the block will - // get executed even if we abort - this.ensured = []; - this.blocks = []; - this.running = false; - this.index = 0; - this.offset = 0; - this.abort = false; -}; - -jasmine.Queue.prototype.addBefore = function(block, ensure) { - if (ensure === jasmine.undefined) { - ensure = false; - } - - this.blocks.unshift(block); - this.ensured.unshift(ensure); -}; - -jasmine.Queue.prototype.add = function(block, ensure) { - if (ensure === jasmine.undefined) { - ensure = false; - } - - this.blocks.push(block); - this.ensured.push(ensure); -}; - -jasmine.Queue.prototype.insertNext = function(block, ensure) { - if (ensure === jasmine.undefined) { - ensure = false; - } - - this.ensured.splice((this.index + this.offset + 1), 0, ensure); - this.blocks.splice((this.index + this.offset + 1), 0, block); - this.offset++; -}; - -jasmine.Queue.prototype.start = function(onComplete) { - this.running = true; - this.onComplete = onComplete; - this.next_(); -}; - -jasmine.Queue.prototype.isRunning = function() { - return this.running; -}; - -jasmine.Queue.LOOP_DONT_RECURSE = true; - -jasmine.Queue.prototype.next_ = function() { - var self = this; - var goAgain = true; - - while (goAgain) { - goAgain = false; - - if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) { - var calledSynchronously = true; - var completedSynchronously = false; - - var onComplete = function () { - if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { - completedSynchronously = true; - return; - } - - if (self.blocks[self.index].abort) { - self.abort = true; - } - - self.offset = 0; - self.index++; - - var now = new Date().getTime(); - if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { - self.env.lastUpdate = now; - self.env.setTimeout(function() { - self.next_(); - }, 0); - } else { - if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { - goAgain = true; - } else { - self.next_(); - } - } - }; - self.blocks[self.index].execute(onComplete); - - calledSynchronously = false; - if (completedSynchronously) { - onComplete(); - } - - } else { - self.running = false; - if (self.onComplete) { - self.onComplete(); - } - } - } -}; - -jasmine.Queue.prototype.results = function() { - var results = new jasmine.NestedResults(); - for (var i = 0; i < this.blocks.length; i++) { - if (this.blocks[i].results) { - results.addResult(this.blocks[i].results()); - } - } - return results; -}; - - -/** - * Runner - * - * @constructor - * @param {jasmine.Env} env - */ -jasmine.Runner = function(env) { - var self = this; - self.env = env; - self.queue = new jasmine.Queue(env); - self.before_ = []; - self.after_ = []; - self.suites_ = []; -}; - -jasmine.Runner.prototype.execute = function() { - var self = this; - if (self.env.reporter.reportRunnerStarting) { - self.env.reporter.reportRunnerStarting(this); - } - self.queue.start(function () { - self.finishCallback(); - }); -}; - -jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.splice(0,0,beforeEachFunction); -}; - -jasmine.Runner.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.splice(0,0,afterEachFunction); -}; - - -jasmine.Runner.prototype.finishCallback = function() { - this.env.reporter.reportRunnerResults(this); -}; - -jasmine.Runner.prototype.addSuite = function(suite) { - this.suites_.push(suite); -}; - -jasmine.Runner.prototype.add = function(block) { - if (block instanceof jasmine.Suite) { - this.addSuite(block); - } - this.queue.add(block); -}; - -jasmine.Runner.prototype.specs = function () { - var suites = this.suites(); - var specs = []; - for (var i = 0; i < suites.length; i++) { - specs = specs.concat(suites[i].specs()); - } - return specs; -}; - -jasmine.Runner.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Runner.prototype.topLevelSuites = function() { - var topLevelSuites = []; - for (var i = 0; i < this.suites_.length; i++) { - if (!this.suites_[i].parentSuite) { - topLevelSuites.push(this.suites_[i]); - } - } - return topLevelSuites; -}; - -jasmine.Runner.prototype.results = function() { - return this.queue.results(); -}; -/** - * Internal representation of a Jasmine specification, or test. - * - * @constructor - * @param {jasmine.Env} env - * @param {jasmine.Suite} suite - * @param {String} description - */ -jasmine.Spec = function(env, suite, description) { - if (!env) { - throw new Error('jasmine.Env() required'); - } - if (!suite) { - throw new Error('jasmine.Suite() required'); - } - var spec = this; - spec.id = env.nextSpecId ? env.nextSpecId() : null; - spec.env = env; - spec.suite = suite; - spec.description = description; - spec.queue = new jasmine.Queue(env); - - spec.afterCallbacks = []; - spec.spies_ = []; - - spec.results_ = new jasmine.NestedResults(); - spec.results_.description = description; - spec.matchersClass = null; -}; - -jasmine.Spec.prototype.getFullName = function() { - return this.suite.getFullName() + ' ' + this.description + '.'; -}; - - -jasmine.Spec.prototype.results = function() { - return this.results_; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.Spec.prototype.log = function() { - return this.results_.log(arguments); -}; - -jasmine.Spec.prototype.runs = function (func) { - var block = new jasmine.Block(this.env, func, this); - this.addToQueue(block); - return this; -}; - -jasmine.Spec.prototype.addToQueue = function (block) { - if (this.queue.isRunning()) { - this.queue.insertNext(block); - } else { - this.queue.add(block); - } -}; - -/** - * @param {jasmine.ExpectationResult} result - */ -jasmine.Spec.prototype.addMatcherResult = function(result) { - this.results_.addResult(result); -}; - -jasmine.Spec.prototype.expect = function(actual) { - var positive = new (this.getMatchersClass_())(this.env, actual, this); - positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); - return positive; -}; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -jasmine.Spec.prototype.waits = function(timeout) { - var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); - this.addToQueue(waitsFunc); - return this; -}; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - var latchFunction_ = null; - var optional_timeoutMessage_ = null; - var optional_timeout_ = null; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - switch (typeof arg) { - case 'function': - latchFunction_ = arg; - break; - case 'string': - optional_timeoutMessage_ = arg; - break; - case 'number': - optional_timeout_ = arg; - break; - } - } - - var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); - this.addToQueue(waitsForFunc); - return this; -}; - -jasmine.Spec.prototype.fail = function (e) { - var expectationResult = new jasmine.ExpectationResult({ - passed: false, - message: e ? jasmine.util.formatException(e) : 'Exception', - trace: { stack: e.stack } - }); - this.results_.addResult(expectationResult); -}; - -jasmine.Spec.prototype.getMatchersClass_ = function() { - return this.matchersClass || this.env.matchersClass; -}; - -jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { - var parent = this.getMatchersClass_(); - var newMatchersClass = function() { - parent.apply(this, arguments); - }; - jasmine.util.inherit(newMatchersClass, parent); - jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); - this.matchersClass = newMatchersClass; -}; - -jasmine.Spec.prototype.finishCallback = function() { - this.env.reporter.reportSpecResults(this); -}; - -jasmine.Spec.prototype.finish = function(onComplete) { - this.removeAllSpies(); - this.finishCallback(); - if (onComplete) { - onComplete(); - } -}; - -jasmine.Spec.prototype.after = function(doAfter) { - if (this.queue.isRunning()) { - this.queue.add(new jasmine.Block(this.env, doAfter, this), true); - } else { - this.afterCallbacks.unshift(doAfter); - } -}; - -jasmine.Spec.prototype.execute = function(onComplete) { - var spec = this; - if (!spec.env.specFilter(spec)) { - spec.results_.skipped = true; - spec.finish(onComplete); - return; - } - - this.env.reporter.reportSpecStarting(this); - - spec.env.currentSpec = spec; - - spec.addBeforesAndAftersToQueue(); - - spec.queue.start(function () { - spec.finish(onComplete); - }); -}; - -jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { - var runner = this.env.currentRunner(); - var i; - - for (var suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); - } - } - for (i = 0; i < runner.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); - } - for (i = 0; i < this.afterCallbacks.length; i++) { - this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true); - } - for (suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true); - } - } - for (i = 0; i < runner.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true); - } -}; - -jasmine.Spec.prototype.explodes = function() { - throw 'explodes function should not have been called'; -}; - -jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { - if (obj == jasmine.undefined) { - throw "spyOn could not find an object to spy upon for " + methodName + "()"; - } - - if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { - throw methodName + '() method does not exist'; - } - - if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { - throw new Error(methodName + ' has already been spied upon'); - } - - var spyObj = jasmine.createSpy(methodName); - - this.spies_.push(spyObj); - spyObj.baseObj = obj; - spyObj.methodName = methodName; - spyObj.originalValue = obj[methodName]; - - obj[methodName] = spyObj; - - return spyObj; -}; - -jasmine.Spec.prototype.removeAllSpies = function() { - for (var i = 0; i < this.spies_.length; i++) { - var spy = this.spies_[i]; - spy.baseObj[spy.methodName] = spy.originalValue; - } - this.spies_ = []; -}; - -/** - * Internal representation of a Jasmine suite. - * - * @constructor - * @param {jasmine.Env} env - * @param {String} description - * @param {Function} specDefinitions - * @param {jasmine.Suite} parentSuite - */ -jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - var self = this; - self.id = env.nextSuiteId ? env.nextSuiteId() : null; - self.description = description; - self.queue = new jasmine.Queue(env); - self.parentSuite = parentSuite; - self.env = env; - self.before_ = []; - self.after_ = []; - self.children_ = []; - self.suites_ = []; - self.specs_ = []; -}; - -jasmine.Suite.prototype.getFullName = function() { - var fullName = this.description; - for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - fullName = parentSuite.description + ' ' + fullName; - } - return fullName; -}; - -jasmine.Suite.prototype.finish = function(onComplete) { - this.env.reporter.reportSuiteResults(this); - this.finished = true; - if (typeof(onComplete) == 'function') { - onComplete(); - } -}; - -jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.unshift(beforeEachFunction); -}; - -jasmine.Suite.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.unshift(afterEachFunction); -}; - -jasmine.Suite.prototype.results = function() { - return this.queue.results(); -}; - -jasmine.Suite.prototype.add = function(suiteOrSpec) { - this.children_.push(suiteOrSpec); - if (suiteOrSpec instanceof jasmine.Suite) { - this.suites_.push(suiteOrSpec); - this.env.currentRunner().addSuite(suiteOrSpec); - } else { - this.specs_.push(suiteOrSpec); - } - this.queue.add(suiteOrSpec); -}; - -jasmine.Suite.prototype.specs = function() { - return this.specs_; -}; - -jasmine.Suite.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Suite.prototype.children = function() { - return this.children_; -}; - -jasmine.Suite.prototype.execute = function(onComplete) { - var self = this; - this.queue.start(function () { - self.finish(onComplete); - }); -}; -jasmine.WaitsBlock = function(env, timeout, spec) { - this.timeout = timeout; - jasmine.Block.call(this, env, null, spec); -}; - -jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); - -jasmine.WaitsBlock.prototype.execute = function (onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); - } - this.env.setTimeout(function () { - onComplete(); - }, this.timeout); -}; -/** - * A block which waits for some condition to become true, with timeout. - * - * @constructor - * @extends jasmine.Block - * @param {jasmine.Env} env The Jasmine environment. - * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. - * @param {Function} latchFunction A function which returns true when the desired condition has been met. - * @param {String} message The message to display if the desired condition hasn't been met within the given time period. - * @param {jasmine.Spec} spec The Jasmine spec. - */ -jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { - this.timeout = timeout || env.defaultTimeoutInterval; - this.latchFunction = latchFunction; - this.message = message; - this.totalTimeSpentWaitingForLatch = 0; - jasmine.Block.call(this, env, null, spec); -}; -jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); - -jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; - -jasmine.WaitsForBlock.prototype.execute = function(onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); - } - var latchFunctionResult; - try { - latchFunctionResult = this.latchFunction.apply(this.spec); - } catch (e) { - this.spec.fail(e); - onComplete(); - return; - } - - if (latchFunctionResult) { - onComplete(); - } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { - var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); - this.spec.fail({ - name: 'timeout', - message: message - }); - - this.abort = true; - onComplete(); - } else { - this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; - var self = this; - this.env.setTimeout(function() { - self.execute(onComplete); - }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); - } -}; - -jasmine.version_= { - "major": 1, - "minor": 3, - "build": 0, - "revision": 1354052693 -}; diff --git a/test/spec/xmlToJSONSpec.js b/test/spec/xmlToJSONSpec.js deleted file mode 100644 index dbc39f1..0000000 --- a/test/spec/xmlToJSONSpec.js +++ /dev/null @@ -1,115 +0,0 @@ - -describe("Version", function() { - - it("print version", function() { - expect(xmlToJSON.version).toMatch(/^1\.3/); - }); - -}); - -describe("Parsing - grokAttr=true, grokText=true", function() { - - var xml; - var result; - var options = {grokAttr: true, grokText: true}; - - it("Setting up xml, options", function () { - options = {}; - xml = ['', - '', - ' ', - ' one', - ' true', - ' false', - ' ]]>two', - ' three', - ' ', - ' true', - ' false', - ''].join('\n'); - - console.debug(xml); - result = xmlToJSON.parseString(xml, options); - console.log(JSON.stringify(result)) - - expect(result).toBeDefined(); - }); - - it("reading text node", function() { - expect(result.xml[0].a[0].b[0]._text).toEqual("one"); - }); - - it("reading numeric attribute", function() { - expect(result.xml[0].a[0].b[0]._attr.id._value).toEqual(1); - }); - - it("reading true attribute", function() { - expect(result.xml[0].a[0].b[1]._attr.id._value).toEqual(true); - }); - - it("reading false attribute", function() { - expect(result.xml[0].a[0].b[2]._attr.id._value).toEqual(false); - }); - - it("reading true node", function() { - expect(result.xml[0].e[0]._text).toEqual(true); - }); - - it("reading false node", function() { - expect(result.xml[0].f[0]._text).toEqual(false); - }); - -}); - -describe("Parsing - grokAttr=false, grokTest=false", function() { - - var xml; - var result; - var options = {grokAttr: false, grokText: false}; - - it("Setting up xml, options", function () { - xml = ['', - '', - ' ', - ' one', - ' true', - ' false', - ' ]]>two', - ' three', - ' ', - ' true', - ' false', - ''].join('\n'); - - console.debug(xml); - result = xmlToJSON.parseString(xml, options); - console.log(JSON.stringify(result)) - - expect(result).toBeDefined(); - }); - - it("reading text node", function() { - expect(result.xml[0].a[0].b[0]._text).toEqual("one"); - }); - - it("reading numeric attribute", function() { - expect(result.xml[0].a[0].b[0]._attr.id._value).toEqual("1"); - }); - - it("reading true attribute", function() { - expect(result.xml[0].a[0].b[1]._attr.id._value).toEqual("true"); - }); - - it("reading false attribute", function() { - expect(result.xml[0].a[0].b[2]._attr.id._value).toEqual("false"); - }); - - it("reading true node", function() { - expect(result.xml[0].e[0]._text).toEqual("true"); - }); - - it("reading false node", function() { - expect(result.xml[0].f[0]._text).toEqual("false"); - }); - -}); From f34c394100c0b1b09056de242088d2fd8889ac33 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 08:00:03 -0500 Subject: [PATCH 02/38] init v3 --- README.md | 430 +++++- examples/browser-example.html | 357 +++++ jest.config.js | 61 +- package-lock.json | 2681 +++++++++++++++++++++++++++++++-- package.json | 83 +- src/XMLParser.ts | 196 +++ src/XMLSerializer.ts | 262 ++++ src/XMLToJSON.ts | 418 +++++ src/config.ts | 39 + src/dom-adapter.ts | 197 +++ src/errors.ts | 61 + src/helpers.ts | 54 + src/index.ts | 27 + src/types.ts | 41 + tsconfig.json | 16 + 15 files changed, 4751 insertions(+), 172 deletions(-) create mode 100644 examples/browser-example.html create mode 100644 src/XMLParser.ts create mode 100644 src/XMLSerializer.ts create mode 100644 src/XMLToJSON.ts create mode 100644 src/config.ts create mode 100644 src/dom-adapter.ts create mode 100644 src/errors.ts create mode 100644 src/helpers.ts create mode 100644 src/index.ts create mode 100644 src/types.ts create mode 100644 tsconfig.json diff --git a/README.md b/README.md index 6c2fc68..d306be3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -xmlToJSON -========= +# XMLToJSON version 1 A simple javascript module for converting XML into JSON within the browser. @@ -138,3 +137,430 @@ results in } ``` + +# XMLToJSON version 3 + +A modern ESM library for converting between XML and JSON with support for namespaces, attributes, and various node types. Works in both browser and Node.js environments through a hybrid DOM implementation approach. + +[![npm version](https://img.shields.io/npm/v/xmltojson.svg)](https://www.npmjs.com/package/xmltojson) +[![License](https://img.shields.io/npm/l/xmltojson.svg)](https://github.com/yourusername/xmltojson/blob/main/LICENSE) +[![Build Status](https://img.shields.io/github/workflow/status/yourusername/xmltojson/CI)](https://github.com/yourusername/xmltojson/actions) +[![Coverage Status](https://img.shields.io/codecov/c/github/yourusername/xmltojson)](https://codecov.io/gh/yourusername/xmltojson) + +## Features + +- **Symmetric Conversion**: Transform XML to JSON and back with no data loss +- **Namespace Support**: Preserve namespaces in both XML and JSON +- **Node Type Preservation**: Support for CDATA, comments, processing instructions, and text nodes +- **Highly Configurable**: Customize property names, output format, and preservation options +- **TypeScript Support**: Full TypeScript definitions for better development experience +- **ESM Compatible**: Modern module system for both Node.js and browser environments +- **Hybrid DOM Support**: Flexible DOM implementation with support for browsers, JSDOM, and xmldom + +## Installation + +```bash +npm install xmltojson +``` + +### Node.js Dependencies + +For Node.js environments, you'll need to install one of these DOM implementations: + +```bash +# Option 1: JSDOM (recommended, more complete DOM implementation) +npm install jsdom + +# Option 2: xmldom (lightweight alternative) +npm install @xmldom/xmldom +``` + +## Usage + +### Basic Usage + +```javascript +import XMLToJSON from 'xmltojson'; + +// Create a converter with default settings +const converter = new XMLToJSON(); + +// Convert XML to JSON +const xmlString = ` + + + Example + This is a with comments + + + + +`; + +const jsonObj = converter.xmlToJson(xmlString); +console.log(JSON.stringify(jsonObj, null, 2)); + +// Convert back to XML +const xmlResult = converter.jsonToXml(jsonObj); +console.log(xmlResult); + +// Clean up resources when done (especially important when using JSDOM) +converter.cleanup(); +``` + +### Custom Configuration + +```javascript +import XMLToJSON from 'xmltojson'; + +// Create a converter with custom settings +const converter = new XMLToJSON({ + // Features to preserve during transformation + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveWhitespace: false, + + // Output options + outputOptions: { + prettyPrint: true, + indent: 3, + compact: true, // removes empty or null nodes and elements + // JSON-specific options + json: { + // Additional JSON options can be added here + }, + // XML-specific options + xml: { + declaration: true, // include the declaration if not present + }, + }, + + // Property names in the JSON representation + propNames: { + namespace: "@ns", + prefix: "@prefix", + attributes: "@attrs", + value: "@val", + cdata: "@cdata", + comments: "@comments", + processing: "@processing", + children: "@children", + }, +}); + +// Use the converter with custom settings +const jsonObj = converter.xmlToJson(xmlString); +``` + +### Using a Custom DOM Implementation + +The library allows you to provide your own DOM implementation, which is useful for specialized environments or testing: + +```javascript +import XMLToJSON from 'xmltojson'; +import { DOMImplementation } from 'xmltojson'; + +// Node.js example with xmldom +const { DOMParser, XMLSerializer, DOMImplementation: XmlDomImpl } = require('@xmldom/xmldom'); + +// Create custom DOM implementation +const domImpl = new XmlDomImpl(); +const customDOM = { + parser: new DOMParser(), + serializer: new XMLSerializer(), + document: domImpl.createDocument(null, null, null), + createDocument: () => domImpl.createDocument(null, null, null) +}; + +// Create converter with custom DOM implementation +const converter = new XMLToJSON({}, customDOM); + +// Use the converter +const json = converter.xmlToJson(xmlString); + +// Clean up resources when done +converter.cleanup(); +``` + +### Node.js Usage with JSDOM + +```javascript +import XMLToJSON from 'xmltojson'; +import { JSDOM } from 'jsdom'; + +// Create a converter (will auto-detect JSDOM if installed) +const converter = new XMLToJSON(); + +// ... use as normal ... + +// Clean up resources when done +converter.cleanup(); +``` + +## JSON Structure + +The library uses a consistent structure for representing XML in JSON: + +```json +{ + "Root_node": { + "@attrs": [ + { + "attr": { + "@ns": "", + "@prefix": "", + "@val": "" + } + } + ], + "@ns": "", + "@prefix": "", + "@children": [ + { + "node_name": { + "@attrs": [ + { + "attr": { + "@ns": "", + "@prefix": "", + "@val": "" + } + } + ], + "@ns": "", + "@children": [ + { + "@processing": { + "target": "target", + "data": "data" + } + }, + { + "@comments": "comment text" + }, + { + "@cdata": "cdata text" + }, + { + "@val": "text content" + } + ] + } + } + ] + } +} +``` + +## Browser Support + +This library works in all modern browsers that support the DOM and ES modules. + +## Node.js Support + +For Node.js environments, you need to install either: + +- `jsdom` (recommended, more complete DOM implementation) +- `@xmldom/xmldom` (lightweight alternative) + +The library will automatically detect which one is available. + +## API Reference + +### Class: XMLToJSON + +The main class for XML to JSON conversion. + +#### Constructor + +```typescript +constructor( + config?: Partial, + customDOMImplementation?: DOMImplementation +) +``` + +Creates a new converter instance with optional configuration and DOM implementation. + +#### Methods + +##### `xmlToJson(xmlString: string): Record` + +Converts an XML string to a JSON object. + +- **Parameters**: + - `xmlString`: The XML content to convert +- **Returns**: A JSON object representing the XML content + +##### `jsonToXml(jsonObj: Record): string` + +Converts a JSON object to an XML string. + +- **Parameters**: + - `jsonObj`: The JSON object to convert +- **Returns**: XML string + +##### `cleanup(): void` + +Cleans up any resources, especially important when using JSDOM. + +### Interface: XMLToJSONConfig + +Configuration interface for XMLToJSON. + +```typescript +interface XMLToJSONConfig { + // Features to preserve during transformation + preserveNamespaces: boolean; + preserveComments: boolean; + preserveProcessingInstr: boolean; + preserveCDATA: boolean; + preserveTextNodes: boolean; + preserveWhitespace: boolean; + + // Output options + outputOptions: { + prettyPrint: boolean; + indent: number; + compact: boolean; + json: Record; + xml: { + declaration: boolean; + }; + }; + + // Property names in the JSON representation + propNames: { + namespace: string; + prefix: string; + attributes: string; + value: string; + cdata: string; + comments: string; + processing: string; + children: string; + }; +} +``` + +### Class: DOMAdapter + +Provides a unified interface for DOM operations across different environments. + +#### Constructor + +```typescript +constructor(customImplementation?: DOMImplementation) +``` + +Creates a new DOMAdapter with an optional custom implementation. + +### Interface: DOMImplementation + +Interface for custom DOM implementations. + +```typescript +interface DOMImplementation { + parser: any; + serializer: any; + document: any; + createDocument: () => Document; +} +``` + +## Examples + +See the [examples](./examples) directory for detailed usage examples: + +- [Browser Usage](./examples/browser-example.html) +- [Node.js with JSDOM](./examples/node-example.js) +- [Custom DOM Implementation](./examples/custom-dom-example.ts) + +## Configuration Options + +### Preservation Options + +| Option | Description | Default | +|--------|-------------|---------| +| `preserveNamespaces` | Preserve XML namespaces in JSON | `true` | +| `preserveComments` | Preserve XML comments in JSON | `true` | +| `preserveProcessingInstr` | Preserve XML processing instructions in JSON | `true` | +| `preserveCDATA` | Preserve CDATA sections in JSON | `true` | +| `preserveTextNodes` | Preserve text nodes separately in JSON | `true` | +| `preserveWhitespace` | Preserve whitespace-only text nodes | `false` | + +### Output Options + +| Option | Description | Default | +|--------|-------------|---------| +| `prettyPrint` | Format XML output with indentation | `true` | +| `indent` | Number of spaces for indentation | `2` | +| `compact` | Remove empty/null properties | `true` | +| `declaration` | Include XML declaration | `true` | + +### Property Names + +| Option | Description | Default | +|--------|-------------|---------| +| `namespace` | Property name for namespace URI | `"@ns"` | +| `prefix` | Property name for namespace prefix | `"@prefix"` | +| `attributes` | Property name for attributes | `"@attrs"` | +| `value` | Property name for text content | `"@val"` | +| `cdata` | Property name for CDATA sections | `"@cdata"` | +| `comments` | Property name for comments | `"@comments"` | +| `processing` | Property name for processing instructions | `"@processing"` | +| `children` | Property name for child nodes | `"@children"` | + +## Performance Considerations + +- For large XML documents, consider using the lightweight `@xmldom/xmldom` in Node.js +- The `compact` option removes empty properties, reducing JSON size +- Disable unneeded preservation options for better performance + +## Troubleshooting + +- **DOM implementation not found in Node.js**: Install either `jsdom` or `@xmldom/xmldom` +- **Memory leaks with JSDOM**: Always call `converter.cleanup()` when done +- **XML parsing errors**: Ensure the XML is well-formed + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add some amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## Development + +```bash +# Install dependencies +npm install + +# Build the library +npm run build + +# Run tests +npm test + +# Run tests with coverage +npm run test:coverage + +# Lint code +npm run lint + +# Format code +npm run format + +# Generate documentation +npm run docs +``` + +## License + +This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details. \ No newline at end of file diff --git a/examples/browser-example.html b/examples/browser-example.html new file mode 100644 index 0000000..689a431 --- /dev/null +++ b/examples/browser-example.html @@ -0,0 +1,357 @@ + + + + + + XMLToJSON Browser Example + + + +

XMLToJSON Browser Example

+ +
+

Configuration

+
+
+

Preservation Options

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+

Output Options

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+

Property Names

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+ + + +
+ +
+
+

XML

+ +
+ +
+

JSON

+ +
+
+ + + + \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 8d28335..65a967a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,27 +1,36 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ -export default { - preset: 'ts-jest/presets/default-esm', - testEnvironment: 'node', - extensionsToTreatAsEsm: ['.ts'], - globals: { - 'ts-jest': { - useESM: true - } - }, - moduleNameMapper: { - '^(\.{1,2}/.*)\.js$': '$1' - } - }; - - // src/index.ts - export function greet(name: string): string { - return `Hello, ${name}!`; - } - - // test/index.test.ts - import { greet } from '../src/index.js'; - - test('greet returns the correct message', () => { - expect(greet('World')).toBe('Hello, World!'); - }); - \ No newline at end of file +const config = { + preset: 'ts-jest/presets/default-esm', + testEnvironment: 'jsdom', + extensionsToTreatAsEsm: ['.ts'], + moduleNameMapper: { + '^(\\.{1,2}/.*)\\.js$': '$1', + }, + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + useESM: true, + }, + ], + }, + coverageDirectory: 'coverage', + collectCoverageFrom: [ + 'src/**/*.ts', + '!src/**/*.d.ts', + '!src/**/index.ts', + ], + testMatch: [ + '**/__tests__/**/*.ts?(x)', + '**/?(*.)+(spec|test).ts?(x)' + ], + testPathIgnorePatterns: [ + '/node_modules/', + '/dist/' + ], + setupFilesAfterEnv: [ + '/jest.setup.js' + ] +}; + +export default config; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 19779e6..138a93a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,10 +7,36 @@ "": { "name": "xmltojson", "version": "3.0.0", + "license": "MIT", "devDependencies": { + "@types/jest": "^29.5.0", + "@types/node": "^18.15.11", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", + "eslint": "^8.37.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", "jest": "^29.6.0", + "jest-environment-jsdom": "^29.6.0", + "prettier": "^2.8.7", + "rimraf": "^4.4.1", "ts-jest": "^29.1.1", - "typescript": "^5.3.3" + "typedoc": "^0.24.1", + "typescript": "^5.1.6" + }, + "engines": { + "node": ">=14.16.0" + }, + "peerDependencies": { + "jsdom": "^21.1.1" + }, + "peerDependenciesMeta": { + "@xmldom/xmldom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, "node_modules/@ampproject/remapping": { @@ -513,6 +539,156 @@ "dev": true, "license": "MIT" }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", + "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -885,6 +1061,44 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -912,6 +1126,16 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -994,16 +1218,53 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "22.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", - "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "version": "18.19.86", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.86.tgz", + "integrity": "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~5.26.4" } }, + "node_modules/@types/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -1011,6 +1272,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -1028,120 +1296,471 @@ "dev": true, "license": "MIT" }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, - "license": "MIT", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "color-convert": "^2.0.1" + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { - "node": ">= 8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, - "license": "BSD-3-Clause", + "license": "BSD-2-Clause", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.3.tgz", + "integrity": "sha512-+fksAx9eG3Ab6LDnLs3ZqZa8KVJ/jYnX+D4Qe1azX+LFGFAXqynCQLOdLpNYN/l9e7l6hMWwZbrnctqr6eSQSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, @@ -1311,6 +1930,20 @@ "dev": true, "license": "MIT" }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1455,6 +2088,19 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1506,14 +2152,56 @@ "node": ">= 8" } }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1524,6 +2212,13 @@ } } }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "dev": true, + "license": "MIT" + }, "node_modules/dedent": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", @@ -1539,6 +2234,13 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -1549,6 +2251,16 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -1569,6 +2281,61 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "license": "MIT", + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -1592,68 +2359,503 @@ "dev": true, "license": "ISC" }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "engines": { + "node": ">=0.10" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "MIT" + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "is-arrayish": "^0.2.1" + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/execa": { @@ -1706,6 +2908,50 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1713,6 +2959,23 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -1723,6 +2986,19 @@ "bser": "2.1.1" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -1783,6 +3059,61 @@ "node": ">=8" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1835,6 +3166,31 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -1845,6 +3201,20 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -1880,6 +3250,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -1890,6 +3273,40 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1897,6 +3314,13 @@ "dev": true, "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1907,6 +3331,35 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -1920,6 +3373,19 @@ "node": ">= 0.4" } }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -1927,14 +3393,93 @@ "dev": true, "license": "MIT" }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=10.17.0" + "node": ">=4" } }, "node_modules/import-local": { @@ -2009,6 +3554,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2029,6 +3584,19 @@ "node": ">=6" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2039,6 +3607,23 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -2362,6 +3947,80 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, "node_modules/jest-environment-node": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", @@ -2792,6 +4451,13 @@ "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -2799,6 +4465,20 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -2812,6 +4492,23 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -2832,6 +4529,20 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -2859,6 +4570,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -2869,6 +4587,13 @@ "yallist": "^3.0.2" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -2915,6 +4640,29 @@ "tmpl": "1.0.5" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -2922,6 +4670,16 @@ "dev": true, "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -2936,6 +4694,29 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -2959,6 +4740,16 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2973,6 +4764,13 @@ "dev": true, "license": "MIT" }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -3010,6 +4808,13 @@ "node": ">=8" } }, + "node_modules/nwsapi": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", + "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", + "dev": true, + "license": "MIT" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3036,6 +4841,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3091,6 +4914,19 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -3110,6 +4946,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3147,6 +4996,50 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -3190,6 +5083,45 @@ "node": ">=8" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -3232,6 +5164,29 @@ "node": ">= 6" } }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -3239,12 +5194,40 @@ "dev": true, "funding": [ { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" + "type": "consulting", + "url": "https://feross.org/support" } ], "license": "MIT" @@ -3266,6 +5249,13 @@ "node": ">=0.10.0" } }, + "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==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -3320,6 +5310,125 @@ "node": ">=10" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^9.2.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -3353,6 +5462,19 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -3519,6 +5641,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -3534,6 +5663,13 @@ "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -3554,6 +5690,35 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-jest": { "version": "29.3.2", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz", @@ -3630,6 +5795,42 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -3653,10 +5854,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedoc": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3668,12 +5917,22 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -3705,6 +5964,27 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.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==", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -3720,6 +6000,33 @@ "node": ">=10.12.0" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -3730,6 +6037,53 @@ "makeerror": "1.0.12" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3746,6 +6100,16 @@ "node": ">= 8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -3785,6 +6149,45 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 8dc7054..9a263bd 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,94 @@ { "name": "xmltojson", "version": "3.0.0", - "description": "A modern ESM library for Node and browser use.", + "description": "A modern ESM library for bidirectional XML to JSON conversion with namespace and node type support.", "type": "module", "main": "./dist/index.js", + "types": "./dist/index.d.ts", "exports": { ".": { - "import": "./dist/index.js" + "import": "./dist/index.js", + "types": "./dist/index.d.ts" } }, + "files": [ + "dist", + "LICENSE", + "README.md", + "package.json" + ], "scripts": { - "build": "tsc", - "test": "jest" + "clean": "rimraf dist", + "build": "npm run clean && tsc", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "lint": "eslint ./src --ext .ts", + "lint:fix": "eslint ./src --ext .ts --fix", + "format": "prettier --write \"src/**/*.ts\"", + "docs": "typedoc --out docs src/index.ts", + "prepublishOnly": "npm run build && npm run test", + "preversion": "npm run lint", + "version": "npm run format && git add -A src", + "postversion": "git push && git push --tags" }, + "keywords": [ + "xml", + "json", + "convert", + "transform", + "parser", + "serializer", + "namespace", + "cdata", + "comment", + "processing-instruction", + "esm", + "browser", + "node" + ], + "author": { + "name": "Your Name", + "email": "your.email@example.com", + "url": "https://your-website.com" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/yourusername/xmltojson.git" + }, + "bugs": { + "url": "https://github.com/yourusername/xmltojson/issues" + }, + "homepage": "https://github.com/yourusername/xmltojson#readme", "devDependencies": { + "@types/jest": "^29.5.0", + "@types/node": "^18.15.11", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", + "eslint": "^8.37.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", "jest": "^29.6.0", + "jest-environment-jsdom": "^29.6.0", + "prettier": "^2.8.7", + "rimraf": "^4.4.1", "ts-jest": "^29.1.1", - "typescript": "^5.3.3" + "typedoc": "^0.24.1", + "typescript": "^5.1.6" + }, + "peerDependencies": { + "jsdom": "^21.1.1" + }, + "peerDependenciesMeta": { + "jsdom": { + "optional": true + }, + "@xmldom/xmldom": { + "optional": true + } + }, + "engines": { + "node": ">=14.16.0" } } diff --git a/src/XMLParser.ts b/src/XMLParser.ts new file mode 100644 index 0000000..d3ced6e --- /dev/null +++ b/src/XMLParser.ts @@ -0,0 +1,196 @@ +/** + * XMLParser class for converting XML to JSON with consistent namespace handling + */ +import { XMLToJSONConfig } from './types'; +import DEFAULT_CONFIG from './config'; + +/** + * XML Parser for converting XML to JSON + */ +class XMLParser { + private config: XMLToJSONConfig; + private parser: DOMParser | null = null; + + /** + * Constructor for XMLParser + * @param config Configuration options + */ + constructor(config: Partial = {}) { + this.config = { ...DEFAULT_CONFIG, ...config }; + + // Initialize parser for browser environment + if (typeof window !== 'undefined') { + this.parser = new DOMParser(); + } else { + // Node.js environment - dynamically import would be needed + throw new Error("Node.js environment detected. You need to use a Node-compatible XML parser."); + } + } + + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + public parse(xmlString: string): Record { + if (!this.parser) { + throw new Error("XML parser not initialized"); + } + + try { + const xmlDoc = this.parser.parseFromString(xmlString, "text/xml"); + + // Check for parsing errors + const parserError = xmlDoc.querySelector("parsererror"); + if (parserError) { + throw new Error(`XML parsing error: ${parserError.textContent}`); + } + + return this.nodeToJson(xmlDoc.documentElement); + } catch (error) { + throw new Error(`Failed to convert XML to JSON: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Convert a DOM node to JSON representation + * @param node DOM node to convert + * @returns JSON representation of the node + */ + private nodeToJson(node: Node): Record { + const result: Record = {}; + + // Handle element nodes + if (node.nodeType === Node.ELEMENT_NODE) { + const element = node as Element; + const nodeName = element.localName || element.nodeName; + + const nodeObj: Record = {}; + + // Process namespaces if enabled + if (this.config.preserveNamespaces) { + const ns = element.namespaceURI; + if (ns) { + nodeObj[this.config.propNames.namespace] = ns; + } + + const prefix = element.prefix; + if (prefix) { + nodeObj[this.config.propNames.prefix] = prefix; + } + } + + // Process attributes + if (element.attributes.length > 0) { + const attrs: Array> = []; + + for (let i = 0; i < element.attributes.length; i++) { + const attr = element.attributes[i]; + const attrLocalName = attr.localName || attr.name; + + // Create attribute object with consistent structure + const attrObj: Record = { + [attrLocalName]: { + [this.config.propNames.value]: attr.value + } + }; + + // Add namespace info for attribute if present and enabled + if (this.config.preserveNamespaces) { + // Handle attribute namespace + if (attr.namespaceURI) { + attrObj[attrLocalName][this.config.propNames.namespace] = attr.namespaceURI; + } + + // Handle attribute prefix + if (attr.prefix) { + attrObj[attrLocalName][this.config.propNames.prefix] = attr.prefix; + } + } + + attrs.push(attrObj); + } + + if (attrs.length > 0) { + nodeObj[this.config.propNames.attributes] = attrs; + } + } + + // Process child nodes + if (element.childNodes.length > 0) { + const children: Array> = []; + + let hasNonWhitespaceContent = false; + + for (let i = 0; i < element.childNodes.length; i++) { + const child = element.childNodes[i]; + + // Text nodes + if (child.nodeType === Node.TEXT_NODE) { + const text = child.nodeValue || ""; + + // Skip whitespace-only text nodes if whitespace preservation is disabled + if (!this.config.preserveWhitespace && text.trim() === "") { + continue; + } + + if (this.config.preserveTextNodes) { + hasNonWhitespaceContent = true; + children.push({ [this.config.propNames.value]: text }); + } else if (text.trim() !== "") { + // If we're not preserving text nodes as separate entities, + // but the text isn't just whitespace, use it as the node's value + hasNonWhitespaceContent = true; + nodeObj[this.config.propNames.value] = text; + } + } + // CDATA sections + else if (child.nodeType === Node.CDATA_SECTION_NODE && this.config.preserveCDATA) { + children.push({ [this.config.propNames.cdata]: child.nodeValue || "" }); + } + // Comments + else if (child.nodeType === Node.COMMENT_NODE && this.config.preserveComments) { + children.push({ [this.config.propNames.comments]: child.nodeValue || "" }); + } + // Processing instructions + else if (child.nodeType === Node.PROCESSING_INSTRUCTION_NODE && this.config.preserveProcessingInstr) { + children.push({ + [this.config.propNames.processing]: { + target: child.nodeName, + data: child.nodeValue || "" + } + }); + } + // Element nodes (recursive) + else if (child.nodeType === Node.ELEMENT_NODE) { + children.push(this.nodeToJson(child)); + } + } + + if (children.length > 0) { + nodeObj[this.config.propNames.children] = children; + } + } + + // Apply compact option - remove empty properties if enabled + if (this.config.outputOptions.compact) { + Object.keys(nodeObj).forEach(key => { + if ( + nodeObj[key] === null || + nodeObj[key] === undefined || + (Array.isArray(nodeObj[key]) && nodeObj[key].length === 0) || + (typeof nodeObj[key] === 'object' && Object.keys(nodeObj[key]).length === 0) + ) { + delete nodeObj[key]; + } + }); + } + + result[nodeName] = nodeObj; + } + + return result; + } +} + +export default XMLParser; \ No newline at end of file diff --git a/src/XMLSerializer.ts b/src/XMLSerializer.ts new file mode 100644 index 0000000..d17e5d5 --- /dev/null +++ b/src/XMLSerializer.ts @@ -0,0 +1,262 @@ +/** + * XMLSerializer class for converting JSON to XML with consistent namespace handling + */ +import { XMLToJSONConfig } from './types'; +import DEFAULT_CONFIG from './config'; + +/** + * XML Serializer for converting JSON to XML + */ +class XMLSerializerUtil { + private config: XMLToJSONConfig; + private serializer: XMLSerializer | null = null; + + /** + * Constructor for XMLSerializer + * @param config Configuration options + */ + constructor(config: Partial = {}) { + this.config = { ...DEFAULT_CONFIG, ...config }; + + // Initialize serializer for browser environment + if (typeof window !== 'undefined') { + this.serializer = new XMLSerializer(); + } else { + // Node.js environment - dynamically import would be needed + throw new Error("Node.js environment detected. You need to use a Node-compatible XML serializer."); + } + } + + /** + * Convert JSON object to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + public serialize(jsonObj: Record): string { + if (!this.serializer) { + throw new Error("XML serializer not initialized"); + } + + try { + const doc = document.implementation.createDocument(null, null, null); + const rootElement = this.jsonToNode(jsonObj, doc); + + if (rootElement) { + doc.appendChild(rootElement); + } + + // Add XML declaration if specified + let xmlString = this.serializer.serializeToString(doc); + if (this.config.outputOptions.xml.declaration && !xmlString.startsWith('\n' + xmlString; + } + + // Apply pretty printing if enabled + if (this.config.outputOptions.prettyPrint) { + xmlString = this.prettyPrintXml(xmlString); + } + + return xmlString; + } catch (error) { + throw new Error(`Failed to convert JSON to XML: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Convert JSON object to DOM node + * @param jsonObj JSON object to convert + * @param doc Document for creating elements + * @returns DOM Element + */ + private jsonToNode(jsonObj: Record, doc: Document): Element | null { + if (!jsonObj || typeof jsonObj !== 'object') { + return null; + } + + // Get the node name (first key in the object) + const nodeName = Object.keys(jsonObj)[0]; + if (!nodeName) { + return null; + } + + const nodeData = jsonObj[nodeName]; + + // Create element with namespace if available + let element: Element; + const ns = nodeData[this.config.propNames.namespace]; + const prefix = nodeData[this.config.propNames.prefix]; + + if (ns && this.config.preserveNamespaces) { + if (prefix) { + element = doc.createElementNS(ns, `${prefix}:${nodeName}`); + } else { + element = doc.createElementNS(ns, nodeName); + } + } else { + element = doc.createElement(nodeName); + } + + // Process attributes with consistent namespace handling + if (nodeData[this.config.propNames.attributes] && Array.isArray(nodeData[this.config.propNames.attributes])) { + nodeData[this.config.propNames.attributes].forEach((attrObj: Record) => { + const attrName = Object.keys(attrObj)[0]; + if (!attrName) return; + + const attrData = attrObj[attrName]; + const attrValue = attrData[this.config.propNames.value] || ''; + const attrNs = attrData[this.config.propNames.namespace]; + const attrPrefix = attrData[this.config.propNames.prefix]; + + // Handle namespaced attributes consistently + let qualifiedName = attrName; + if (attrPrefix) { + qualifiedName = `${attrPrefix}:${attrName}`; + } + + if (attrNs && this.config.preserveNamespaces) { + element.setAttributeNS(attrNs, qualifiedName, attrValue); + } else { + element.setAttribute(qualifiedName, attrValue); + } + }); + } + + // Process simple text value + if (nodeData[this.config.propNames.value] !== undefined) { + element.textContent = nodeData[this.config.propNames.value]; + } + + // Process children + if (nodeData[this.config.propNames.children] && Array.isArray(nodeData[this.config.propNames.children])) { + nodeData[this.config.propNames.children].forEach((child: Record) => { + // Text nodes + if (child[this.config.propNames.value] !== undefined && this.config.preserveTextNodes) { + element.appendChild(doc.createTextNode(child[this.config.propNames.value])); + } + // CDATA sections + else if (child[this.config.propNames.cdata] !== undefined && this.config.preserveCDATA) { + element.appendChild(doc.createCDATASection(child[this.config.propNames.cdata])); + } + // Comments + else if (child[this.config.propNames.comments] !== undefined && this.config.preserveComments) { + element.appendChild(doc.createComment(child[this.config.propNames.comments])); + } + // Processing instructions + else if (child[this.config.propNames.processing] !== undefined && this.config.preserveProcessingInstr) { + const piData = child[this.config.propNames.processing]; + if (piData.target) { + element.appendChild(doc.createProcessingInstruction(piData.target, piData.data || '')); + } + } + // Element nodes (recursive) + else { + const childElement = this.jsonToNode(child, doc); + if (childElement) { + element.appendChild(childElement); + } + } + }); + } + + return element; + } + + /** + * Apply simple pretty printing to XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + private prettyPrintXml(xmlString: string): string { + // This is a simple implementation + // A production-ready solution would use a proper XML formatter + let formatted = ''; + let indent = 0; + const indentString = ' '.repeat(this.config.outputOptions.indent); + + // Simple state machine for XML formatting + let inTag = false; + let inContent = false; + let inCDATA = false; + let inComment = false; + + for (let i = 0; i < xmlString.length; i++) { + const char = xmlString.charAt(i); + const nextChar = xmlString.charAt(i + 1); + + // Handle CDATA sections + if (char === '<' && xmlString.substr(i, 9) === '') { + inCDATA = false; + formatted += ']]>'; + i += 2; + continue; + } + if (inCDATA) { + formatted += char; + continue; + } + + // Handle comments + if (char === '<' && xmlString.substr(i, 4) === '') { + inComment = false; + formatted += '-->'; + i += 2; + continue; + } + if (inComment) { + formatted += char; + continue; + } + + // Handle tags and content + if (char === '<' && !inTag && !inContent) { + // Check if it's a closing tag + if (nextChar === '/') { + indent -= 1; + } + + if (!inContent) { + formatted += '\n' + indentString.repeat(indent); + } + + formatted += char; + inTag = true; + inContent = false; + } + else if (char === '>' && inTag) { + formatted += char; + inTag = false; + + // Check if it's a self-closing tag + if (xmlString.charAt(i - 1) !== '/') { + inContent = true; + } + + // Check if it's an opening tag (not self-closing) + if (xmlString.charAt(i - 1) !== '/' && xmlString.charAt(i - 1) !== '?') { + indent += 1; + } + } + else if (inContent && char === '<' && nextChar !== '!') { + inContent = false; + i--; // Re-process this character as a tag start + } + else { + formatted += char; + } + } + + return formatted; + } +} + +export default XMLSerializerUtil; \ No newline at end of file diff --git a/src/XMLToJSON.ts b/src/XMLToJSON.ts new file mode 100644 index 0000000..9166b41 --- /dev/null +++ b/src/XMLToJSON.ts @@ -0,0 +1,418 @@ +/** + * XMLToJSON main class with hybrid DOM implementation support + */ +import { XMLToJSONConfig } from './types'; +import DEFAULT_CONFIG from './config'; +import DOMAdapter, { DOMImplementation } from './dom-adapter'; + +/** + * XMLToJSON - Main class for XML to JSON transformation + * Supports both browser and Node.js environments through a hybrid DOM approach + */ +class XMLToJSON { + private config: XMLToJSONConfig; + private domAdapter: DOMAdapter; + + /** + * Constructor for XMLToJSON utility + * @param config Configuration options + * @param customDOMImplementation Optional custom DOM implementation + */ + constructor( + config: Partial = {}, + customDOMImplementation?: DOMImplementation + ) { + this.config = { ...DEFAULT_CONFIG, ...config }; + this.domAdapter = new DOMAdapter(customDOMImplementation); + } + + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + public xmlToJson(xmlString: string): Record { + try { + const xmlDoc = this.domAdapter.parseFromString(xmlString, 'text/xml'); + + // Check for parsing errors - the approach differs between browser and Node.js + // This is a simplified check that works in most environments + const errors = xmlDoc.getElementsByTagName('parsererror'); + if (errors.length > 0) { + throw new Error(`XML parsing error: ${errors[0].textContent}`); + } + + return this.nodeToJson(xmlDoc.documentElement); + } catch (error) { + throw new Error(`Failed to convert XML to JSON: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Convert JSON object back to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + public jsonToXml(jsonObj: Record): string { + try { + const doc = this.domAdapter.createDocument(); + const rootElement = this.jsonToNode(jsonObj, doc); + + if (rootElement) { + doc.appendChild(rootElement); + } + + // Add XML declaration if specified + let xmlString = this.domAdapter.serializeToString(doc); + if (this.config.outputOptions.xml.declaration && !xmlString.startsWith('\n' + xmlString; + } + + // Apply pretty printing if enabled + if (this.config.outputOptions.prettyPrint) { + xmlString = this.prettyPrintXml(xmlString); + } + + return xmlString; + } catch (error) { + throw new Error(`Failed to convert JSON to XML: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Convert a DOM node to JSON representation + * @param node DOM node to convert + * @returns JSON representation of the node + */ + private nodeToJson(node: Node): Record { + const result: Record = {}; + + // Handle element nodes + if (node.nodeType === Node.ELEMENT_NODE) { + const element = node as Element; + const nodeName = element.nodeName; + + const nodeObj: Record = {}; + + // Process namespaces if enabled + if (this.config.preserveNamespaces) { + const ns = element.namespaceURI; + if (ns) { + nodeObj[this.config.propNames.namespace] = ns; + } + + const prefix = element.prefix; + if (prefix) { + nodeObj[this.config.propNames.prefix] = prefix; + } + } + + // Process attributes + if (element.attributes.length > 0) { + const attrs: Array> = []; + + for (let i = 0; i < element.attributes.length; i++) { + const attr = element.attributes[i]; + const attrObj: Record = { + [attr.name]: { + [this.config.propNames.value]: attr.value + } + }; + + // Add namespace info for attribute if present and enabled + if (this.config.preserveNamespaces) { + if (attr.namespaceURI) { + attrObj[attr.name][this.config.propNames.namespace] = attr.namespaceURI; + } + if (attr.prefix) { + attrObj[attr.name][this.config.propNames.prefix] = attr.prefix; + } + } + + attrs.push(attrObj); + } + + if (attrs.length > 0) { + nodeObj[this.config.propNames.attributes] = attrs; + } + } + + // Process child nodes + if (element.childNodes.length > 0) { + const children: Array> = []; + + let hasNonWhitespaceContent = false; + + for (let i = 0; i < element.childNodes.length; i++) { + const child = element.childNodes[i]; + + // Text nodes + if (child.nodeType === Node.TEXT_NODE) { + const text = child.nodeValue || ""; + + // Skip whitespace-only text nodes if whitespace preservation is disabled + if (!this.config.preserveWhitespace && text.trim() === "") { + continue; + } + + if (this.config.preserveTextNodes) { + hasNonWhitespaceContent = true; + children.push({ [this.config.propNames.value]: text }); + } else if (text.trim() !== "") { + // If we're not preserving text nodes as separate entities, + // but the text isn't just whitespace, use it as the node's value + hasNonWhitespaceContent = true; + nodeObj[this.config.propNames.value] = text; + } + } + // CDATA sections + else if (child.nodeType === Node.CDATA_SECTION_NODE && this.config.preserveCDATA) { + children.push({ [this.config.propNames.cdata]: child.nodeValue || "" }); + } + // Comments + else if (child.nodeType === Node.COMMENT_NODE && this.config.preserveComments) { + children.push({ [this.config.propNames.comments]: child.nodeValue || "" }); + } + // Processing instructions + else if (child.nodeType === Node.PROCESSING_INSTRUCTION_NODE && this.config.preserveProcessingInstr) { + children.push({ + [this.config.propNames.processing]: { + target: child.nodeName, + data: child.nodeValue || "" + } + }); + } + // Element nodes (recursive) + else if (child.nodeType === Node.ELEMENT_NODE) { + children.push(this.nodeToJson(child)); + } + } + + if (children.length > 0) { + nodeObj[this.config.propNames.children] = children; + } + } + + // Apply compact option - remove empty properties if enabled + if (this.config.outputOptions.compact) { + Object.keys(nodeObj).forEach(key => { + if ( + nodeObj[key] === null || + nodeObj[key] === undefined || + (Array.isArray(nodeObj[key]) && nodeObj[key].length === 0) || + (typeof nodeObj[key] === 'object' && Object.keys(nodeObj[key]).length === 0) + ) { + delete nodeObj[key]; + } + }); + } + + result[nodeName] = nodeObj; + } + + return result; + } + + /** + * Convert JSON object to DOM node + * @param jsonObj JSON object to convert + * @param doc Document for creating elements + * @returns DOM Element + */ + private jsonToNode(jsonObj: Record, doc: Document): Element | null { + if (!jsonObj || typeof jsonObj !== 'object') { + return null; + } + + // Get the node name (first key in the object) + const nodeName = Object.keys(jsonObj)[0]; + if (!nodeName) { + return null; + } + + const nodeData = jsonObj[nodeName]; + + // Create element with namespace if available + let element: Element; + const ns = nodeData[this.config.propNames.namespace]; + const prefix = nodeData[this.config.propNames.prefix]; + + if (ns && this.config.preserveNamespaces) { + if (prefix) { + element = this.domAdapter.createElementNS(ns, `${prefix}:${nodeName}`); + } else { + element = this.domAdapter.createElementNS(ns, nodeName); + } + } else { + element = this.domAdapter.createElement(nodeName); + } + + // Process attributes + if (nodeData[this.config.propNames.attributes] && Array.isArray(nodeData[this.config.propNames.attributes])) { + nodeData[this.config.propNames.attributes].forEach((attrObj: Record) => { + const attrName = Object.keys(attrObj)[0]; + if (!attrName) return; + + const attrData = attrObj[attrName]; + const attrValue = attrData[this.config.propNames.value] || ''; + const attrNs = attrData[this.config.propNames.namespace]; + const attrPrefix = attrData[this.config.propNames.prefix]; + + if (attrNs && this.config.preserveNamespaces) { + if (attrPrefix) { + element.setAttributeNS(attrNs, `${attrPrefix}:${attrName}`, attrValue); + } else { + element.setAttributeNS(attrNs, attrName, attrValue); + } + } else { + element.setAttribute(attrName, attrValue); + } + }); + } + + // Process simple text value + if (nodeData[this.config.propNames.value] !== undefined) { + element.textContent = nodeData[this.config.propNames.value]; + } + + // Process children + if (nodeData[this.config.propNames.children] && Array.isArray(nodeData[this.config.propNames.children])) { + nodeData[this.config.propNames.children].forEach((child: Record) => { + // Text nodes + if (child[this.config.propNames.value] !== undefined && this.config.preserveTextNodes) { + element.appendChild(this.domAdapter.createTextNode(child[this.config.propNames.value])); + } + // CDATA sections + else if (child[this.config.propNames.cdata] !== undefined && this.config.preserveCDATA) { + element.appendChild(this.domAdapter.createCDATASection(child[this.config.propNames.cdata])); + } + // Comments + else if (child[this.config.propNames.comments] !== undefined && this.config.preserveComments) { + element.appendChild(this.domAdapter.createComment(child[this.config.propNames.comments])); + } + // Processing instructions + else if (child[this.config.propNames.processing] !== undefined && this.config.preserveProcessingInstr) { + const piData = child[this.config.propNames.processing]; + if (piData.target) { + element.appendChild(this.domAdapter.createProcessingInstruction(piData.target, piData.data || '')); + } + } + // Element nodes (recursive) + else { + const childElement = this.jsonToNode(child, doc); + if (childElement) { + element.appendChild(childElement); + } + } + }); + } + + return element; + } + + /** + * Apply simple pretty printing to XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + private prettyPrintXml(xmlString: string): string { + // This is a simple implementation + // A production-ready solution would use a proper XML formatter + let formatted = ''; + let indent = 0; + const indentString = ' '.repeat(this.config.outputOptions.indent); + + // Simple state machine for XML formatting + let inTag = false; + let inContent = false; + let inCDATA = false; + let inComment = false; + + for (let i = 0; i < xmlString.length; i++) { + const char = xmlString.charAt(i); + const nextChar = xmlString.charAt(i + 1); + + // Handle CDATA sections + if (char === '<' && xmlString.substr(i, 9) === '') { + inCDATA = false; + formatted += ']]>'; + i += 2; + continue; + } + if (inCDATA) { + formatted += char; + continue; + } + + // Handle comments + if (char === '<' && xmlString.substr(i, 4) === '') { + inComment = false; + formatted += '-->'; + i += 2; + continue; + } + if (inComment) { + formatted += char; + continue; + } + + // Handle tags and content + if (char === '<' && !inTag && !inContent) { + // Check if it's a closing tag + if (nextChar === '/') { + indent -= 1; + } + + if (!inContent) { + formatted += '\n' + indentString.repeat(indent); + } + + formatted += char; + inTag = true; + inContent = false; + } + else if (char === '>' && inTag) { + formatted += char; + inTag = false; + + // Check if it's a self-closing tag + if (xmlString.charAt(i - 1) !== '/') { + inContent = true; + } + + // Check if it's an opening tag (not self-closing) + if (xmlString.charAt(i - 1) !== '/' && xmlString.charAt(i - 1) !== '?') { + indent += 1; + } + } + else if (inContent && char === '<' && nextChar !== '!') { + inContent = false; + i--; // Re-process this character as a tag start + } + else { + formatted += char; + } + } + + return formatted; + } + + /** + * Clean up any resources (especially for JSDOM) + */ + public cleanup(): void { + this.domAdapter.cleanup(); + } +} + +export default XMLToJSON; \ No newline at end of file diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..3b53c76 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,39 @@ +/** + * Default configuration for XMLToJSON + */ +import { XMLToJSONConfig } from './types'; + +/** + * Default configuration for XMLToJSON + */ +export const DEFAULT_CONFIG: XMLToJSONConfig = { + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveWhitespace: false, + + outputOptions: { + prettyPrint: true, + indent: 2, + compact: true, + json: {}, + xml: { + declaration: true, + }, + }, + + propNames: { + namespace: "@ns", + prefix: "@prefix", + attributes: "@attrs", + value: "@val", + cdata: "@cdata", + comments: "@comments", + processing: "@processing", + children: "@children", + }, +}; + +export default DEFAULT_CONFIG; \ No newline at end of file diff --git a/src/dom-adapter.ts b/src/dom-adapter.ts new file mode 100644 index 0000000..17bac32 --- /dev/null +++ b/src/dom-adapter.ts @@ -0,0 +1,197 @@ +/** + * DOM Adapter for XMLToJSON + * Provides a unified interface for DOM operations across different environments. + */ +import { isNode, isBrowser } from './helpers'; +import { EnvironmentError } from './errors'; + +/** + * Interface for DOM implementation + */ +export interface DOMImplementation { + parser: any; + serializer: any; + document: any; + createDocument: () => Document; +} + +/** + * Creates a DOM implementation based on the environment or provided implementation + */ +export class DOMAdapter { + private _parser: any; + private _serializer: any; + private _document: any; + private _implementation: any; + private _jsdomInstance: any = null; + + /** + * Create a new DOMAdapter + * @param customImplementation Optional custom DOM implementation + */ + constructor(customImplementation?: DOMImplementation) { + if (customImplementation) { + // Use custom implementation if provided + this._parser = customImplementation.parser; + this._serializer = customImplementation.serializer; + this._document = customImplementation.document; + this._implementation = { + createDocument: customImplementation.createDocument + }; + } else if (isBrowser()) { + // Browser environment + this._parser = new DOMParser(); + this._serializer = new XMLSerializer(); + this._document = document; + this._implementation = document.implementation; + } else if (isNode()) { + // Try JSDOM first + try { + const { JSDOM } = require('jsdom'); + this._jsdomInstance = new JSDOM(''); + this._parser = new this._jsdomInstance.window.DOMParser(); + this._serializer = new this._jsdomInstance.window.XMLSerializer(); + this._document = this._jsdomInstance.window.document; + this._implementation = this._jsdomInstance.window.document.implementation; + } catch (jsdomError) { + // Fall back to xmldom if JSDOM isn't available + try { + const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom'); + this._parser = new DOMParser(); + this._serializer = new XMLSerializer(); + this._implementation = new DOMImplementation(); + this._document = this._implementation.createDocument(null, null, null); + } catch (xmldomError) { + throw new EnvironmentError( + "Node.js environment detected. Please install either 'jsdom' or '@xmldom/xmldom' package, or provide a custom DOM implementation." + ); + } + } + } else { + throw new EnvironmentError("Unsupported environment"); + } + } + + /** + * Get the DOMParser instance + */ + get parser() { + return this._parser; + } + + /** + * Get the XMLSerializer instance + */ + get serializer() { + return this._serializer; + } + + /** + * Get the Document instance + */ + get document() { + return this._document; + } + + /** + * Parse XML string to DOM + * @param xmlString XML string to parse + * @param mimeType MIME type for parsing (default: 'text/xml') + * @returns Parsed Document + */ + parseFromString(xmlString: string, mimeType: string = 'text/xml'): Document { + try { + return this._parser.parseFromString(xmlString, mimeType); + } catch (error) { + throw new Error(`XML parsing error: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Serialize DOM to XML string + * @param doc Document to serialize + * @returns XML string + */ + serializeToString(doc: Document): string { + try { + return this._serializer.serializeToString(doc); + } catch (error) { + throw new Error(`XML serialization error: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Create a new empty XML document + * @returns New Document + */ + createDocument(): Document { + return this._implementation.createDocument(null, null, null); + } + + /** + * Create a text node + * @param data Text content + * @returns Text node + */ + createTextNode(data: string): Text { + return this._document.createTextNode(data); + } + + /** + * Create a CDATA section + * @param data CDATA content + * @returns CDATASection node + */ + createCDATASection(data: string): CDATASection { + return this._document.createCDATASection(data); + } + + /** + * Create a comment node + * @param data Comment content + * @returns Comment node + */ + createComment(data: string): Comment { + return this._document.createComment(data); + } + + /** + * Create a processing instruction + * @param target Target + * @param data Processing instruction data + * @returns ProcessingInstruction node + */ + createProcessingInstruction(target: string, data: string): ProcessingInstruction { + return this._document.createProcessingInstruction(target, data); + } + + /** + * Create an element + * @param tagName Element tag name + * @returns Element + */ + createElement(tagName: string): Element { + return this._document.createElement(tagName); + } + + /** + * Create an element with namespace + * @param namespaceURI Namespace URI + * @param qualifiedName Qualified name (with prefix) + * @returns Element + */ + createElementNS(namespaceURI: string, qualifiedName: string): Element { + return this._document.createElementNS(namespaceURI, qualifiedName); + } + + /** + * Clean up any resources (especially for JSDOM) + */ + cleanup(): void { + if (this._jsdomInstance) { + this._jsdomInstance.window.close(); + } + } +} + +export default DOMAdapter; \ No newline at end of file diff --git a/src/errors.ts b/src/errors.ts new file mode 100644 index 0000000..e925dec --- /dev/null +++ b/src/errors.ts @@ -0,0 +1,61 @@ +/** + * Error classes for XMLToJSON + */ + +/** + * Base error class for XMLToJSON + */ +export class XMLToJSONError extends Error { + constructor(message: string) { + super(message); + this.name = 'XMLToJSONError'; + } + } + + /** + * Error for XML parsing issues + */ + export class XMLParseError extends XMLToJSONError { + constructor(message: string) { + super(`XML parse error: ${message}`); + this.name = 'XMLParseError'; + } + } + + /** + * Error for XML serialization issues + */ + export class XMLSerializeError extends XMLToJSONError { + constructor(message: string) { + super(`XML serialize error: ${message}`); + this.name = 'XMLSerializeError'; + } + } + + /** + * Error for environment incompatibility + */ + export class EnvironmentError extends XMLToJSONError { + constructor(message: string) { + super(`Environment error: ${message}`); + this.name = 'EnvironmentError'; + } + } + + /** + * Error for invalid configuration + */ + export class ConfigurationError extends XMLToJSONError { + constructor(message: string) { + super(`Configuration error: ${message}`); + this.name = 'ConfigurationError'; + } + } + + export default { + XMLToJSONError, + XMLParseError, + XMLSerializeError, + EnvironmentError, + ConfigurationError + }; \ No newline at end of file diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..83ca276 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,54 @@ +/** + * Helper functions for XMLToJSON + */ + +/** + * Determines if the current environment is a browser + * @returns true if running in browser, false otherwise + */ +export const isBrowser = (): boolean => { + return typeof window !== 'undefined' && typeof window.document !== 'undefined'; + }; + + /** + * Determines if the current environment is Node.js + * @returns true if running in Node.js, false otherwise + */ + export const isNode = (): boolean => { + return typeof process !== 'undefined' && + process.versions != null && + process.versions.node != null; + }; + + /** + * Check if an object is empty + * @param obj Object to check + * @returns true if object is empty, false otherwise + */ + export const isEmptyObject = (obj: any): boolean => { + if (!obj) return true; + if (typeof obj !== 'object') return false; + if (Array.isArray(obj)) return obj.length === 0; + return Object.keys(obj).length === 0; + }; + + /** + * Safely stringify JSON for debugging + * @param obj Object to stringify + * @param indent Optional indentation level + * @returns JSON string representation + */ + export const safeStringify = (obj: any, indent: number = 2): string => { + try { + return JSON.stringify(obj, null, indent); + } catch (error) { + return '[Cannot stringify object]'; + } + }; + + export default { + isBrowser, + isNode, + isEmptyObject, + safeStringify + }; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..696b673 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,27 @@ +/** + * XMLToJSON Library - Main entry point + */ +import XMLToJSON from './XMLToJSON'; +import XMLParser from './XMLParser'; +import XMLSerializerUtil from './XMLSerializer'; +import DOMAdapter, { DOMImplementation } from './dom-adapter'; +import { XMLToJSONConfig } from './types'; +import DEFAULT_CONFIG from './config'; +import * as helpers from './helpers'; +import * as errors from './errors'; + +// Re-export all classes and types +export { + XMLToJSON, + XMLParser, + XMLSerializerUtil, + DOMAdapter, + DOMImplementation, + XMLToJSONConfig, + DEFAULT_CONFIG, + helpers, + errors +}; + +// Default export is the main XMLToJSON class +export default XMLToJSON; \ No newline at end of file diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..c4b75d6 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,41 @@ +/** + * Type definitions for XMLToJSON + */ + +/** + * Configuration interface for XMLToJSON + */ +export interface XMLToJSONConfig { + // Features to preserve during transformation + preserveNamespaces: boolean; + preserveComments: boolean; + preserveProcessingInstr: boolean; + preserveCDATA: boolean; + preserveTextNodes: boolean; + preserveWhitespace: boolean; + + // Output options + outputOptions: { + prettyPrint: boolean; + indent: number; + compact: boolean; + json: Record; + xml: { + declaration: boolean; + }; + }; + + // Property names in the JSON representation + propNames: { + namespace: string; + prefix: string; + attributes: string; + value: string; + cdata: string; + comments: string; + processing: string; + children: string; + }; + } + + export default XMLToJSONConfig; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..290c114 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "Node", + "declaration": true, + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "lib": ["DOM", "ES2020"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "**/*.test.ts"] +} \ No newline at end of file From 1b6868f3ba381b999200c35f4f0a8cdcd4bc82ef Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 08:17:55 -0500 Subject: [PATCH 03/38] fixed build issues removed default exports updated rollup --- examples/browser-example.html | 44 +++- package-lock.json | 378 ++++++++++++++++++++++++++++++++++ package.json | 17 +- rollup.config.js | 82 ++++++++ src/XMLParser.ts | 8 +- src/XMLSerializer.ts | 8 +- src/XMLToJSON.ts | 10 +- src/config.ts | 4 +- src/dom-adapter.ts | 4 +- src/errors.ts | 10 +- src/index.ts | 15 +- tsconfig.json | 5 +- 12 files changed, 532 insertions(+), 53 deletions(-) create mode 100644 rollup.config.js diff --git a/examples/browser-example.html b/examples/browser-example.html index 689a431..73ced05 100644 --- a/examples/browser-example.html +++ b/examples/browser-example.html @@ -240,11 +240,13 @@

JSON

- + diff --git a/package-lock.json b/package-lock.json index 138a93a..e2dabfe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,10 @@ "version": "3.0.0", "license": "MIT", "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^11.1.6", "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@typescript-eslint/eslint-plugin": "^5.57.1", @@ -20,6 +24,8 @@ "jest-environment-jsdom": "^29.6.0", "prettier": "^2.8.7", "rimraf": "^4.4.1", + "rollup": "^3.29.5", + "rollup-plugin-dts": "^5.3.1", "ts-jest": "^29.1.1", "typedoc": "^0.24.1", "typescript": "^5.1.6" @@ -1043,6 +1049,17 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", @@ -1099,6 +1116,187 @@ "node": ">= 8" } }, + "node_modules/@rollup/plugin-commonjs": { + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "11.1.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", + "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1181,6 +1379,13 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -1258,6 +1463,13 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/semver": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", @@ -2101,6 +2313,20 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2848,6 +3074,13 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3597,6 +3830,13 @@ "node": ">=0.10.0" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -3624,6 +3864,16 @@ "dev": true, "license": "MIT" }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4594,6 +4844,16 @@ "dev": true, "license": "MIT" }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -5232,6 +5492,16 @@ ], "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -5385,6 +5655,46 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-dts": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz", + "integrity": "sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "magic-string": "^0.30.2" + }, + "engines": { + "node": ">=v14.21.3" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.22.5" + }, + "peerDependencies": { + "rollup": "^3.0", + "typescript": "^4.1 || ^5.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5409,6 +5719,27 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5439,6 +5770,16 @@ "semver": "bin/semver.js" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5499,6 +5840,13 @@ "node": ">=8" } }, + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "dev": true, + "license": "MIT" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5648,6 +5996,36 @@ "dev": true, "license": "MIT" }, + "node_modules/terser": { + "version": "5.39.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", + "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", diff --git a/package.json b/package.json index 9a263bd..e74388e 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,14 @@ "description": "A modern ESM library for bidirectional XML to JSON conversion with namespace and node type support.", "type": "module", "main": "./dist/index.js", + "module": "./dist/index.js", + "browser": "./dist/xmltojson.umd.js", + "unpkg": "./dist/xmltojson.min.js", "types": "./dist/index.d.ts", "exports": { ".": { "import": "./dist/index.js", + "require": "./dist/xmltojson.umd.js", "types": "./dist/index.d.ts" } }, @@ -19,7 +23,10 @@ ], "scripts": { "clean": "rimraf dist", - "build": "npm run clean && tsc", + "build": "npm run clean && npm run build:types && npm run build:js", + "build:types": "tsc --emitDeclarationOnly --outDir dist/dts", + "build:js": "rollup -c", + "build:prod": "NODE_ENV=production npm run build:js", "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", @@ -27,7 +34,7 @@ "lint:fix": "eslint ./src --ext .ts --fix", "format": "prettier --write \"src/**/*.ts\"", "docs": "typedoc --out docs src/index.ts", - "prepublishOnly": "npm run build && npm run test", + "prepublishOnly": "npm run build:prod && npm run test", "preversion": "npm run lint", "version": "npm run format && git add -A src", "postversion": "git push && git push --tags" @@ -62,6 +69,10 @@ }, "homepage": "https://github.com/yourusername/xmltojson#readme", "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^11.1.6", "@types/jest": "^29.5.0", "@types/node": "^18.15.11", "@typescript-eslint/eslint-plugin": "^5.57.1", @@ -73,6 +84,8 @@ "jest-environment-jsdom": "^29.6.0", "prettier": "^2.8.7", "rimraf": "^4.4.1", + "rollup": "^3.29.5", + "rollup-plugin-dts": "^5.3.1", "ts-jest": "^29.1.1", "typedoc": "^0.24.1", "typescript": "^5.1.6" diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..95cbd66 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,82 @@ +import typescript from '@rollup/plugin-typescript'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import terser from '@rollup/plugin-terser'; +import dts from 'rollup-plugin-dts'; +import { readFileSync } from 'fs'; + +const packageJson = JSON.parse(readFileSync('./package.json', 'utf8')); +const isProd = process.env.NODE_ENV === 'production'; + +const baseConfig = { + input: 'src/index.ts', + external: [...Object.keys(packageJson.peerDependencies || {})], + plugins: [ + nodeResolve({ + browser: true, + extensions: ['.ts', '.js'] + }), + commonjs(), + typescript({ + tsconfig: './tsconfig.json', + declaration: true + }) + ] +}; + +export default [ + // ESM build + { + ...baseConfig, + output: { + file: 'dist/index.js', + format: 'esm', + sourcemap: !isProd, + exports: 'named' + } + }, + // UMD build (browser-compatible) + { + ...baseConfig, + output: { + file: 'dist/xmltojson.umd.js', + format: 'umd', + name: 'XMLToJSON', + sourcemap: !isProd, + exports: 'named', + globals: { + // Define global variable names for external dependencies if any + 'jsdom': 'JSDOM', + '@xmldom/xmldom': 'xmldom' + } + }, + plugins: [ + ...baseConfig.plugins, + isProd && terser() + ].filter(Boolean) + }, + // Browser-specific IIFE build + { + ...baseConfig, + output: { + file: 'dist/xmltojson.min.js', + format: 'iife', + name: 'XMLToJSON', + sourcemap: !isProd, + exports: 'named' + }, + plugins: [ + ...baseConfig.plugins, + terser() + ] + }, + // Type definitions + { + input: 'dist/dts/index.d.ts', + output: { + file: 'dist/index.d.ts', + format: 'es' + }, + plugins: [dts()] + } +]; \ No newline at end of file diff --git a/src/XMLParser.ts b/src/XMLParser.ts index d3ced6e..dce8759 100644 --- a/src/XMLParser.ts +++ b/src/XMLParser.ts @@ -2,12 +2,12 @@ * XMLParser class for converting XML to JSON with consistent namespace handling */ import { XMLToJSONConfig } from './types'; -import DEFAULT_CONFIG from './config'; +import { DEFAULT_CONFIG } from './config'; /** * XML Parser for converting XML to JSON */ -class XMLParser { +export class XMLParser { private config: XMLToJSONConfig; private parser: DOMParser | null = null; @@ -191,6 +191,4 @@ class XMLParser { return result; } -} - -export default XMLParser; \ No newline at end of file +} \ No newline at end of file diff --git a/src/XMLSerializer.ts b/src/XMLSerializer.ts index d17e5d5..16c3b6f 100644 --- a/src/XMLSerializer.ts +++ b/src/XMLSerializer.ts @@ -2,12 +2,12 @@ * XMLSerializer class for converting JSON to XML with consistent namespace handling */ import { XMLToJSONConfig } from './types'; -import DEFAULT_CONFIG from './config'; +import { DEFAULT_CONFIG } from './config'; /** * XML Serializer for converting JSON to XML */ -class XMLSerializerUtil { +export class XMLSerializerUtil { private config: XMLToJSONConfig; private serializer: XMLSerializer | null = null; @@ -257,6 +257,4 @@ class XMLSerializerUtil { return formatted; } -} - -export default XMLSerializerUtil; \ No newline at end of file +} \ No newline at end of file diff --git a/src/XMLToJSON.ts b/src/XMLToJSON.ts index 9166b41..218647f 100644 --- a/src/XMLToJSON.ts +++ b/src/XMLToJSON.ts @@ -2,14 +2,14 @@ * XMLToJSON main class with hybrid DOM implementation support */ import { XMLToJSONConfig } from './types'; -import DEFAULT_CONFIG from './config'; -import DOMAdapter, { DOMImplementation } from './dom-adapter'; +import { DEFAULT_CONFIG } from './config'; +import { DOMAdapter, DOMImplementation } from './dom-adapter'; /** * XMLToJSON - Main class for XML to JSON transformation * Supports both browser and Node.js environments through a hybrid DOM approach */ -class XMLToJSON { +export class XMLToJSON { private config: XMLToJSONConfig; private domAdapter: DOMAdapter; @@ -413,6 +413,4 @@ class XMLToJSON { public cleanup(): void { this.domAdapter.cleanup(); } -} - -export default XMLToJSON; \ No newline at end of file +} \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 3b53c76..00f6426 100644 --- a/src/config.ts +++ b/src/config.ts @@ -34,6 +34,4 @@ export const DEFAULT_CONFIG: XMLToJSONConfig = { processing: "@processing", children: "@children", }, -}; - -export default DEFAULT_CONFIG; \ No newline at end of file +}; \ No newline at end of file diff --git a/src/dom-adapter.ts b/src/dom-adapter.ts index 17bac32..32e91b0 100644 --- a/src/dom-adapter.ts +++ b/src/dom-adapter.ts @@ -192,6 +192,4 @@ export class DOMAdapter { this._jsdomInstance.window.close(); } } -} - -export default DOMAdapter; \ No newline at end of file +} \ No newline at end of file diff --git a/src/errors.ts b/src/errors.ts index e925dec..02fb063 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -50,12 +50,4 @@ export class XMLToJSONError extends Error { super(`Configuration error: ${message}`); this.name = 'ConfigurationError'; } - } - - export default { - XMLToJSONError, - XMLParseError, - XMLSerializeError, - EnvironmentError, - ConfigurationError - }; \ No newline at end of file + } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 696b673..dbe982f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,12 @@ /** * XMLToJSON Library - Main entry point */ -import XMLToJSON from './XMLToJSON'; -import XMLParser from './XMLParser'; -import XMLSerializerUtil from './XMLSerializer'; -import DOMAdapter, { DOMImplementation } from './dom-adapter'; +import { XMLToJSON } from './XMLToJSON'; +import { XMLParser } from './XMLParser'; +import { XMLSerializerUtil } from './XMLSerializer'; +import { DOMAdapter, DOMImplementation } from './dom-adapter'; import { XMLToJSONConfig } from './types'; -import DEFAULT_CONFIG from './config'; +import { DEFAULT_CONFIG } from './config'; import * as helpers from './helpers'; import * as errors from './errors'; @@ -21,7 +21,4 @@ export { DEFAULT_CONFIG, helpers, errors -}; - -// Default export is the main XMLToJSON class -export default XMLToJSON; \ No newline at end of file +}; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 290c114..3c6e6db 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,8 @@ "module": "ESNext", "moduleResolution": "Node", "declaration": true, - "outDir": "./dist", + "declarationDir": "./dist/dts", + "outDir": "./dist/esm", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, @@ -12,5 +13,5 @@ "lib": ["DOM", "ES2020"] }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "**/*.test.ts"] + "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } \ No newline at end of file From 419dcdcd109fe303c5c2104383f1cd63897cef84 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 08:42:36 -0500 Subject: [PATCH 04/38] named exports --- src/XMLParser.ts | 6 ++++-- src/XMLSerializer.ts | 9 +++++++-- src/XMLToJSON.ts | 31 +++++++++++++++++++++---------- src/index.ts | 4 +++- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/XMLParser.ts b/src/XMLParser.ts index dce8759..007eee8 100644 --- a/src/XMLParser.ts +++ b/src/XMLParser.ts @@ -63,7 +63,8 @@ export class XMLParser { // Handle element nodes if (node.nodeType === Node.ELEMENT_NODE) { const element = node as Element; - const nodeName = element.localName || element.nodeName; + // Use localName instead of nodeName to strip namespace prefix + const nodeName = element.localName || element.nodeName.split(':').pop() || element.nodeName; const nodeObj: Record = {}; @@ -86,7 +87,8 @@ export class XMLParser { for (let i = 0; i < element.attributes.length; i++) { const attr = element.attributes[i]; - const attrLocalName = attr.localName || attr.name; + // Strip namespace prefix from attribute name + const attrLocalName = attr.localName || attr.name.split(':').pop() || attr.name; // Create attribute object with consistent structure const attrObj: Record = { diff --git a/src/XMLSerializer.ts b/src/XMLSerializer.ts index 16c3b6f..a6ebcb8 100644 --- a/src/XMLSerializer.ts +++ b/src/XMLSerializer.ts @@ -88,11 +88,14 @@ export class XMLSerializerUtil { if (ns && this.config.preserveNamespaces) { if (prefix) { + // Create element with namespace and prefix element = doc.createElementNS(ns, `${prefix}:${nodeName}`); } else { + // Create element with namespace but no prefix element = doc.createElementNS(ns, nodeName); } } else { + // Create element without namespace element = doc.createElement(nodeName); } @@ -107,15 +110,17 @@ export class XMLSerializerUtil { const attrNs = attrData[this.config.propNames.namespace]; const attrPrefix = attrData[this.config.propNames.prefix]; - // Handle namespaced attributes consistently + // Form qualified name for attribute if it has a prefix let qualifiedName = attrName; - if (attrPrefix) { + if (attrPrefix && this.config.preserveNamespaces) { qualifiedName = `${attrPrefix}:${attrName}`; } if (attrNs && this.config.preserveNamespaces) { + // Set attribute with namespace element.setAttributeNS(attrNs, qualifiedName, attrValue); } else { + // Set attribute without namespace element.setAttribute(qualifiedName, attrValue); } }); diff --git a/src/XMLToJSON.ts b/src/XMLToJSON.ts index 218647f..bdb7a4a 100644 --- a/src/XMLToJSON.ts +++ b/src/XMLToJSON.ts @@ -90,7 +90,8 @@ export class XMLToJSON { // Handle element nodes if (node.nodeType === Node.ELEMENT_NODE) { const element = node as Element; - const nodeName = element.nodeName; + // Use localName instead of nodeName to strip namespace prefix + const nodeName = element.localName || element.nodeName.split(':').pop() || element.nodeName; const nodeObj: Record = {}; @@ -113,8 +114,11 @@ export class XMLToJSON { for (let i = 0; i < element.attributes.length; i++) { const attr = element.attributes[i]; + // Strip namespace prefix from attribute name + const attrLocalName = attr.localName || attr.name.split(':').pop() || attr.name; + const attrObj: Record = { - [attr.name]: { + [attrLocalName]: { [this.config.propNames.value]: attr.value } }; @@ -122,10 +126,10 @@ export class XMLToJSON { // Add namespace info for attribute if present and enabled if (this.config.preserveNamespaces) { if (attr.namespaceURI) { - attrObj[attr.name][this.config.propNames.namespace] = attr.namespaceURI; + attrObj[attrLocalName][this.config.propNames.namespace] = attr.namespaceURI; } if (attr.prefix) { - attrObj[attr.name][this.config.propNames.prefix] = attr.prefix; + attrObj[attrLocalName][this.config.propNames.prefix] = attr.prefix; } } @@ -239,11 +243,14 @@ export class XMLToJSON { if (ns && this.config.preserveNamespaces) { if (prefix) { + // Create element with namespace and prefix element = this.domAdapter.createElementNS(ns, `${prefix}:${nodeName}`); } else { + // Create element with namespace but no prefix element = this.domAdapter.createElementNS(ns, nodeName); } } else { + // Create element without namespace element = this.domAdapter.createElement(nodeName); } @@ -258,14 +265,18 @@ export class XMLToJSON { const attrNs = attrData[this.config.propNames.namespace]; const attrPrefix = attrData[this.config.propNames.prefix]; + // Form qualified name for attribute if it has a prefix + let qualifiedName = attrName; + if (attrPrefix && this.config.preserveNamespaces) { + qualifiedName = `${attrPrefix}:${attrName}`; + } + if (attrNs && this.config.preserveNamespaces) { - if (attrPrefix) { - element.setAttributeNS(attrNs, `${attrPrefix}:${attrName}`, attrValue); - } else { - element.setAttributeNS(attrNs, attrName, attrValue); - } + // Set attribute with namespace + element.setAttributeNS(attrNs, qualifiedName, attrValue); } else { - element.setAttribute(attrName, attrValue); + // Set attribute without namespace + element.setAttribute(qualifiedName, attrValue); } }); } diff --git a/src/index.ts b/src/index.ts index dbe982f..7db4a5c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,4 +21,6 @@ export { DEFAULT_CONFIG, helpers, errors -}; \ No newline at end of file +}; + +export default XMLToJSON; \ No newline at end of file From 114da6c0d4d066b6035ee112fb3e9b1088b66362 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 09:39:37 -0500 Subject: [PATCH 05/38] improved DOM Adapter --- src/DOMAdapter.ts | 243 +++++++++++++++++++++++++++++++ src/XMLSerializer.ts | 338 +++++++++++++++++++++++-------------------- src/XMLToJSON.ts | 62 ++++---- src/dom-adapter.ts | 195 ------------------------- src/index.ts | 5 +- 5 files changed, 457 insertions(+), 386 deletions(-) create mode 100644 src/DOMAdapter.ts delete mode 100644 src/dom-adapter.ts diff --git a/src/DOMAdapter.ts b/src/DOMAdapter.ts new file mode 100644 index 0000000..d3de021 --- /dev/null +++ b/src/DOMAdapter.ts @@ -0,0 +1,243 @@ +/** + * DOM Environment provider with unified interface for browser and Node.js + */ +import { XMLToJSONError } from './errors'; + +interface NodeTypes { + ELEMENT_NODE: number; + TEXT_NODE: number; + CDATA_SECTION_NODE: number; + COMMENT_NODE: number; + PROCESSING_INSTRUCTION_NODE: number; +} + +interface DOMWindow { + DOMParser: any; + XMLSerializer: any; + Node: { + ELEMENT_NODE: number; + TEXT_NODE: number; + CDATA_SECTION_NODE: number; + COMMENT_NODE: number; + PROCESSING_INSTRUCTION_NODE: number; + }; + document: Document; + close?: () => void; // Added close method as optional +} + +interface JSDOMInstance { + window: DOMWindow; +} + +export const DOMEnvironment = (() => { + // Environment-specific DOM implementation + let domParser: any; + let xmlSerializer: any; + let nodeTypes: NodeTypes; + let docImplementation: any; + let jsdomInstance: JSDOMInstance | null = null; + + try { + if (typeof window === "undefined") { + // Node.js environment - try JSDOM first + try { + const { JSDOM } = require("jsdom"); + jsdomInstance = new JSDOM("", { + contentType: "text/xml", + }) as JSDOMInstance; + + domParser = jsdomInstance.window.DOMParser; + xmlSerializer = jsdomInstance.window.XMLSerializer; + nodeTypes = { + ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE, + TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE, + CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE, + COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE, + PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE, + }; + docImplementation = jsdomInstance.window.document.implementation; + } catch (jsdomError) { + // Fall back to xmldom if JSDOM isn't available + try { + const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom'); + domParser = DOMParser; + xmlSerializer = XMLSerializer; + // Standard DOM node types + nodeTypes = { + ELEMENT_NODE: 1, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + COMMENT_NODE: 8, + PROCESSING_INSTRUCTION_NODE: 7, + }; + const implementation = new DOMImplementation(); + docImplementation = implementation; + } catch (xmldomError) { + throw new XMLToJSONError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`); + } + } + } else { + // Browser environment + if (!window.DOMParser) { + throw new XMLToJSONError("DOMParser is not available in this environment"); + } + + if (!window.XMLSerializer) { + throw new XMLToJSONError("XMLSerializer is not available in this environment"); + } + + domParser = window.DOMParser; + xmlSerializer = window.XMLSerializer; + nodeTypes = { + ELEMENT_NODE: Node.ELEMENT_NODE, + TEXT_NODE: Node.TEXT_NODE, + CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE, + COMMENT_NODE: Node.COMMENT_NODE, + PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE, + }; + docImplementation = document.implementation; + } + } catch (error) { + throw new XMLToJSONError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`); + } + + return { + createParser: () => { + try { + return new domParser(); + } catch (error) { + throw new XMLToJSONError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createSerializer: () => { + try { + return new xmlSerializer(); + } catch (error) { + throw new XMLToJSONError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + nodeTypes, + + parseFromString: (xmlString: string, contentType: string = 'text/xml') => { + try { + const parser = new domParser(); + return parser.parseFromString(xmlString, contentType); + } catch (error) { + throw new XMLToJSONError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + serializeToString: (node: Node) => { + try { + const serializer = new xmlSerializer(); + return serializer.serializeToString(node); + } catch (error) { + throw new XMLToJSONError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createDocument: () => { + try { + // For browsers, create a document with a root element to avoid issues + if (typeof window !== "undefined") { + const parser = new domParser(); + return parser.parseFromString('', 'text/xml'); + } else { + return docImplementation.createDocument(null, null, null); + } + } catch (error) { + throw new XMLToJSONError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createElement: (tagName: string) => { + try { + if (typeof window !== "undefined") { + return document.createElement(tagName); + } else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createElement(tagName); + } + } catch (error) { + throw new XMLToJSONError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createElementNS: (namespaceURI: string, qualifiedName: string) => { + try { + if (typeof window !== "undefined") { + return document.createElementNS(namespaceURI, qualifiedName); + } else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createElementNS(namespaceURI, qualifiedName); + } + } catch (error) { + throw new XMLToJSONError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createTextNode: (data: string) => { + try { + if (typeof window !== "undefined") { + return document.createTextNode(data); + } else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createTextNode(data); + } + } catch (error) { + throw new XMLToJSONError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createCDATASection: (data: string) => { + try { + // For browser compatibility, use document.implementation to create CDATA + if (typeof window !== "undefined") { + const doc = document.implementation.createDocument(null, null, null); + return doc.createCDATASection(data); + } else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createCDATASection(data); + } + } catch (error) { + throw new XMLToJSONError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createComment: (data: string) => { + try { + if (typeof window !== "undefined") { + return document.createComment(data); + } else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createComment(data); + } + } catch (error) { + throw new XMLToJSONError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + createProcessingInstruction: (target: string, data: string) => { + try { + if (typeof window !== "undefined") { + const doc = document.implementation.createDocument(null, null, null); + return doc.createProcessingInstruction(target, data); + } else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createProcessingInstruction(target, data); + } + } catch (error) { + throw new XMLToJSONError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + // Cleanup method (mainly for JSDOM) + cleanup: () => { + if (jsdomInstance && typeof jsdomInstance.window.close === 'function') { + jsdomInstance.window.close(); + } + } + }; +})(); \ No newline at end of file diff --git a/src/XMLSerializer.ts b/src/XMLSerializer.ts index a6ebcb8..03b0fa3 100644 --- a/src/XMLSerializer.ts +++ b/src/XMLSerializer.ts @@ -1,8 +1,9 @@ /** * XMLSerializer class for converting JSON to XML with consistent namespace handling */ -import { XMLToJSONConfig } from './types'; -import { DEFAULT_CONFIG } from './config'; +import { XMLToJSONConfig } from "./types"; +import { DEFAULT_CONFIG } from "./config"; +import { DOMEnvironment } from './DOMAdapter'; /** * XML Serializer for converting JSON to XML @@ -17,13 +18,15 @@ export class XMLSerializerUtil { */ constructor(config: Partial = {}) { this.config = { ...DEFAULT_CONFIG, ...config }; - + // Initialize serializer for browser environment - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { this.serializer = new XMLSerializer(); } else { // Node.js environment - dynamically import would be needed - throw new Error("Node.js environment detected. You need to use a Node-compatible XML serializer."); + throw new Error( + "Node.js environment detected. You need to use a Node-compatible XML serializer." + ); } } @@ -40,25 +43,32 @@ export class XMLSerializerUtil { try { const doc = document.implementation.createDocument(null, null, null); const rootElement = this.jsonToNode(jsonObj, doc); - + if (rootElement) { doc.appendChild(rootElement); } - + // Add XML declaration if specified let xmlString = this.serializer.serializeToString(doc); - if (this.config.outputOptions.xml.declaration && !xmlString.startsWith('\n' + xmlString; } - + // Apply pretty printing if enabled if (this.config.outputOptions.prettyPrint) { xmlString = this.prettyPrintXml(xmlString); } - + return xmlString; } catch (error) { - throw new Error(`Failed to convert JSON to XML: ${error instanceof Error ? error.message : String(error)}`); + throw new Error( + `Failed to convert JSON to XML: ${ + error instanceof Error ? error.message : String(error) + }` + ); } } @@ -68,24 +78,27 @@ export class XMLSerializerUtil { * @param doc Document for creating elements * @returns DOM Element */ - private jsonToNode(jsonObj: Record, doc: Document): Element | null { - if (!jsonObj || typeof jsonObj !== 'object') { + private jsonToNode( + jsonObj: Record, + doc: Document + ): Element | null { + if (!jsonObj || typeof jsonObj !== "object") { return null; } - + // Get the node name (first key in the object) const nodeName = Object.keys(jsonObj)[0]; if (!nodeName) { return null; } - + const nodeData = jsonObj[nodeName]; - + // Create element with namespace if available let element: Element; const ns = nodeData[this.config.propNames.namespace]; const prefix = nodeData[this.config.propNames.prefix]; - + if (ns && this.config.preserveNamespaces) { if (prefix) { // Create element with namespace and prefix @@ -98,168 +111,177 @@ export class XMLSerializerUtil { // Create element without namespace element = doc.createElement(nodeName); } - + // Process attributes with consistent namespace handling - if (nodeData[this.config.propNames.attributes] && Array.isArray(nodeData[this.config.propNames.attributes])) { - nodeData[this.config.propNames.attributes].forEach((attrObj: Record) => { - const attrName = Object.keys(attrObj)[0]; - if (!attrName) return; - - const attrData = attrObj[attrName]; - const attrValue = attrData[this.config.propNames.value] || ''; - const attrNs = attrData[this.config.propNames.namespace]; - const attrPrefix = attrData[this.config.propNames.prefix]; - - // Form qualified name for attribute if it has a prefix - let qualifiedName = attrName; - if (attrPrefix && this.config.preserveNamespaces) { - qualifiedName = `${attrPrefix}:${attrName}`; - } - - if (attrNs && this.config.preserveNamespaces) { - // Set attribute with namespace - element.setAttributeNS(attrNs, qualifiedName, attrValue); - } else { - // Set attribute without namespace - element.setAttribute(qualifiedName, attrValue); + if ( + nodeData[this.config.propNames.attributes] && + Array.isArray(nodeData[this.config.propNames.attributes]) + ) { + nodeData[this.config.propNames.attributes].forEach( + (attrObj: Record) => { + const attrName = Object.keys(attrObj)[0]; + if (!attrName) return; + + const attrData = attrObj[attrName]; + const attrValue = attrData[this.config.propNames.value] || ""; + const attrNs = attrData[this.config.propNames.namespace]; + const attrPrefix = attrData[this.config.propNames.prefix]; + + // Form qualified name for attribute if it has a prefix + let qualifiedName = attrName; + if (attrPrefix && this.config.preserveNamespaces) { + qualifiedName = `${attrPrefix}:${attrName}`; + } + + if (attrNs && this.config.preserveNamespaces) { + // Set attribute with namespace + element.setAttributeNS(attrNs, qualifiedName, attrValue); + } else { + // Set attribute without namespace + element.setAttribute(qualifiedName, attrValue); + } } - }); + ); } - + // Process simple text value if (nodeData[this.config.propNames.value] !== undefined) { element.textContent = nodeData[this.config.propNames.value]; } - + // Process children - if (nodeData[this.config.propNames.children] && Array.isArray(nodeData[this.config.propNames.children])) { - nodeData[this.config.propNames.children].forEach((child: Record) => { - // Text nodes - if (child[this.config.propNames.value] !== undefined && this.config.preserveTextNodes) { - element.appendChild(doc.createTextNode(child[this.config.propNames.value])); - } - // CDATA sections - else if (child[this.config.propNames.cdata] !== undefined && this.config.preserveCDATA) { - element.appendChild(doc.createCDATASection(child[this.config.propNames.cdata])); - } - // Comments - else if (child[this.config.propNames.comments] !== undefined && this.config.preserveComments) { - element.appendChild(doc.createComment(child[this.config.propNames.comments])); - } - // Processing instructions - else if (child[this.config.propNames.processing] !== undefined && this.config.preserveProcessingInstr) { - const piData = child[this.config.propNames.processing]; - if (piData.target) { - element.appendChild(doc.createProcessingInstruction(piData.target, piData.data || '')); + if ( + nodeData[this.config.propNames.children] && + Array.isArray(nodeData[this.config.propNames.children]) + ) { + nodeData[this.config.propNames.children].forEach( + (child: Record) => { + // Text nodes + if ( + child[this.config.propNames.value] !== undefined && + this.config.preserveTextNodes + ) { + element.appendChild( + doc.createTextNode(child[this.config.propNames.value]) + ); } - } - // Element nodes (recursive) - else { - const childElement = this.jsonToNode(child, doc); - if (childElement) { - element.appendChild(childElement); + // CDATA sections + else if ( + child[this.config.propNames.cdata] !== undefined && + this.config.preserveCDATA + ) { + element.appendChild( + doc.createCDATASection(child[this.config.propNames.cdata]) + ); + } + // Comments + else if ( + child[this.config.propNames.comments] !== undefined && + this.config.preserveComments + ) { + element.appendChild( + doc.createComment(child[this.config.propNames.comments]) + ); + } + // Processing instructions + else if ( + child[this.config.propNames.processing] !== undefined && + this.config.preserveProcessingInstr + ) { + const piData = child[this.config.propNames.processing]; + if (piData.target) { + element.appendChild( + doc.createProcessingInstruction( + piData.target, + piData.data || "" + ) + ); + } + } + // Element nodes (recursive) + else { + const childElement = this.jsonToNode(child, doc); + if (childElement) { + element.appendChild(childElement); + } } } - }); + ); } - + return element; } /** - * Apply simple pretty printing to XML string + * Pretty print an XML string * @param xmlString XML string to format * @returns Formatted XML string */ private prettyPrintXml(xmlString: string): string { - // This is a simple implementation - // A production-ready solution would use a proper XML formatter - let formatted = ''; - let indent = 0; - const indentString = ' '.repeat(this.config.outputOptions.indent); - - // Simple state machine for XML formatting - let inTag = false; - let inContent = false; - let inCDATA = false; - let inComment = false; - - for (let i = 0; i < xmlString.length; i++) { - const char = xmlString.charAt(i); - const nextChar = xmlString.charAt(i + 1); - - // Handle CDATA sections - if (char === '<' && xmlString.substr(i, 9) === '') { - inCDATA = false; - formatted += ']]>'; - i += 2; - continue; - } - if (inCDATA) { - formatted += char; - continue; - } - - // Handle comments - if (char === '<' && xmlString.substr(i, 4) === '') { - inComment = false; - formatted += '-->'; - i += 2; - continue; - } - if (inComment) { - formatted += char; - continue; - } - - // Handle tags and content - if (char === '<' && !inTag && !inContent) { - // Check if it's a closing tag - if (nextChar === '/') { - indent -= 1; - } - - if (!inContent) { - formatted += '\n' + indentString.repeat(indent); - } - - formatted += char; - inTag = true; - inContent = false; - } - else if (char === '>' && inTag) { - formatted += char; - inTag = false; - - // Check if it's a self-closing tag - if (xmlString.charAt(i - 1) !== '/') { - inContent = true; + const INDENT = + typeof this.config.outputOptions.indent === "number" + ? " ".repeat(this.config.outputOptions.indent) + : " "; + + const doc = DOMEnvironment.parseFromString(xmlString, 'text/xml'); + + const serializer = (node: Node, level = 0): string => { + const pad = INDENT.repeat(level); + + switch (node.nodeType) { + case Node.ELEMENT_NODE: { + const el = node as Element; + const tagName = el.tagName; + const attrs = Array.from(el.attributes) + .map((a) => `${a.name}="${a.value}"`) + .join(" "); + const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`; + + const children = Array.from(el.childNodes); + if (children.length === 0) { + return `${pad}${openTag.replace(/>$/, " />")}\n`; + } + + // Single text node: print inline + if ( + children.length === 1 && + children[0].nodeType === Node.TEXT_NODE && + children[0].textContent?.trim() !== "" + ) { + return `${pad}${openTag}${children[0].textContent}\n`; + } + + const inner = children + .map((child) => serializer(child, level + 1)) + .join(""); + return `${pad}${openTag}\n${inner}${pad}\n`; } - - // Check if it's an opening tag (not self-closing) - if (xmlString.charAt(i - 1) !== '/' && xmlString.charAt(i - 1) !== '?') { - indent += 1; + + case Node.TEXT_NODE: { + const text = node.textContent?.trim(); + return text ? `${pad}${text}\n` : ""; } + + case Node.CDATA_SECTION_NODE: + return `${pad}\n`; + + case Node.COMMENT_NODE: + return `${pad}\n`; + + case Node.PROCESSING_INSTRUCTION_NODE: + const pi = node as ProcessingInstruction; + return `${pad}\n`; + + case Node.DOCUMENT_NODE: + return Array.from(node.childNodes) + .map((child) => serializer(child, level)) + .join(""); + + default: + return ""; } - else if (inContent && char === '<' && nextChar !== '!') { - inContent = false; - i--; // Re-process this character as a tag start - } - else { - formatted += char; - } - } - - return formatted; + }; + + return serializer(doc).trim(); } -} \ No newline at end of file +} diff --git a/src/XMLToJSON.ts b/src/XMLToJSON.ts index bdb7a4a..16b961a 100644 --- a/src/XMLToJSON.ts +++ b/src/XMLToJSON.ts @@ -3,27 +3,21 @@ */ import { XMLToJSONConfig } from './types'; import { DEFAULT_CONFIG } from './config'; -import { DOMAdapter, DOMImplementation } from './dom-adapter'; +import { DOMEnvironment } from './DOMAdapter'; /** * XMLToJSON - Main class for XML to JSON transformation - * Supports both browser and Node.js environments through a hybrid DOM approach + * Supports both browser and Node.js environments */ export class XMLToJSON { private config: XMLToJSONConfig; - private domAdapter: DOMAdapter; /** * Constructor for XMLToJSON utility * @param config Configuration options - * @param customDOMImplementation Optional custom DOM implementation */ - constructor( - config: Partial = {}, - customDOMImplementation?: DOMImplementation - ) { + constructor(config: Partial = {}) { this.config = { ...DEFAULT_CONFIG, ...config }; - this.domAdapter = new DOMAdapter(customDOMImplementation); } /** @@ -33,10 +27,9 @@ export class XMLToJSON { */ public xmlToJson(xmlString: string): Record { try { - const xmlDoc = this.domAdapter.parseFromString(xmlString, 'text/xml'); + const xmlDoc = DOMEnvironment.parseFromString(xmlString, 'text/xml'); - // Check for parsing errors - the approach differs between browser and Node.js - // This is a simplified check that works in most environments + // Check for parsing errors const errors = xmlDoc.getElementsByTagName('parsererror'); if (errors.length > 0) { throw new Error(`XML parsing error: ${errors[0].textContent}`); @@ -55,15 +48,20 @@ export class XMLToJSON { */ public jsonToXml(jsonObj: Record): string { try { - const doc = this.domAdapter.createDocument(); + const doc = DOMEnvironment.createDocument(); const rootElement = this.jsonToNode(jsonObj, doc); if (rootElement) { - doc.appendChild(rootElement); + // Handle the temporary root element if it exists + if (doc.documentElement && doc.documentElement.nodeName === 'temp') { + doc.replaceChild(rootElement, doc.documentElement); + } else { + doc.appendChild(rootElement); + } } // Add XML declaration if specified - let xmlString = this.domAdapter.serializeToString(doc); + let xmlString = DOMEnvironment.serializeToString(doc); if (this.config.outputOptions.xml.declaration && !xmlString.startsWith('\n' + xmlString; } @@ -88,7 +86,7 @@ export class XMLToJSON { const result: Record = {}; // Handle element nodes - if (node.nodeType === Node.ELEMENT_NODE) { + if (node.nodeType === DOMEnvironment.nodeTypes.ELEMENT_NODE) { const element = node as Element; // Use localName instead of nodeName to strip namespace prefix const nodeName = element.localName || element.nodeName.split(':').pop() || element.nodeName; @@ -117,6 +115,7 @@ export class XMLToJSON { // Strip namespace prefix from attribute name const attrLocalName = attr.localName || attr.name.split(':').pop() || attr.name; + // Create attribute object with consistent structure const attrObj: Record = { [attrLocalName]: { [this.config.propNames.value]: attr.value @@ -125,9 +124,12 @@ export class XMLToJSON { // Add namespace info for attribute if present and enabled if (this.config.preserveNamespaces) { + // Handle attribute namespace if (attr.namespaceURI) { attrObj[attrLocalName][this.config.propNames.namespace] = attr.namespaceURI; } + + // Handle attribute prefix if (attr.prefix) { attrObj[attrLocalName][this.config.propNames.prefix] = attr.prefix; } @@ -151,7 +153,7 @@ export class XMLToJSON { const child = element.childNodes[i]; // Text nodes - if (child.nodeType === Node.TEXT_NODE) { + if (child.nodeType === DOMEnvironment.nodeTypes.TEXT_NODE) { const text = child.nodeValue || ""; // Skip whitespace-only text nodes if whitespace preservation is disabled @@ -170,15 +172,15 @@ export class XMLToJSON { } } // CDATA sections - else if (child.nodeType === Node.CDATA_SECTION_NODE && this.config.preserveCDATA) { + else if (child.nodeType === DOMEnvironment.nodeTypes.CDATA_SECTION_NODE && this.config.preserveCDATA) { children.push({ [this.config.propNames.cdata]: child.nodeValue || "" }); } // Comments - else if (child.nodeType === Node.COMMENT_NODE && this.config.preserveComments) { + else if (child.nodeType === DOMEnvironment.nodeTypes.COMMENT_NODE && this.config.preserveComments) { children.push({ [this.config.propNames.comments]: child.nodeValue || "" }); } // Processing instructions - else if (child.nodeType === Node.PROCESSING_INSTRUCTION_NODE && this.config.preserveProcessingInstr) { + else if (child.nodeType === DOMEnvironment.nodeTypes.PROCESSING_INSTRUCTION_NODE && this.config.preserveProcessingInstr) { children.push({ [this.config.propNames.processing]: { target: child.nodeName, @@ -187,7 +189,7 @@ export class XMLToJSON { }); } // Element nodes (recursive) - else if (child.nodeType === Node.ELEMENT_NODE) { + else if (child.nodeType === DOMEnvironment.nodeTypes.ELEMENT_NODE) { children.push(this.nodeToJson(child)); } } @@ -244,14 +246,14 @@ export class XMLToJSON { if (ns && this.config.preserveNamespaces) { if (prefix) { // Create element with namespace and prefix - element = this.domAdapter.createElementNS(ns, `${prefix}:${nodeName}`); + element = DOMEnvironment.createElementNS(ns, `${prefix}:${nodeName}`); } else { // Create element with namespace but no prefix - element = this.domAdapter.createElementNS(ns, nodeName); + element = DOMEnvironment.createElementNS(ns, nodeName); } } else { // Create element without namespace - element = this.domAdapter.createElement(nodeName); + element = DOMEnvironment.createElement(nodeName); } // Process attributes @@ -291,21 +293,21 @@ export class XMLToJSON { nodeData[this.config.propNames.children].forEach((child: Record) => { // Text nodes if (child[this.config.propNames.value] !== undefined && this.config.preserveTextNodes) { - element.appendChild(this.domAdapter.createTextNode(child[this.config.propNames.value])); + element.appendChild(DOMEnvironment.createTextNode(child[this.config.propNames.value])); } // CDATA sections else if (child[this.config.propNames.cdata] !== undefined && this.config.preserveCDATA) { - element.appendChild(this.domAdapter.createCDATASection(child[this.config.propNames.cdata])); + element.appendChild(DOMEnvironment.createCDATASection(child[this.config.propNames.cdata])); } // Comments else if (child[this.config.propNames.comments] !== undefined && this.config.preserveComments) { - element.appendChild(this.domAdapter.createComment(child[this.config.propNames.comments])); + element.appendChild(DOMEnvironment.createComment(child[this.config.propNames.comments])); } // Processing instructions else if (child[this.config.propNames.processing] !== undefined && this.config.preserveProcessingInstr) { const piData = child[this.config.propNames.processing]; if (piData.target) { - element.appendChild(this.domAdapter.createProcessingInstruction(piData.target, piData.data || '')); + element.appendChild(DOMEnvironment.createProcessingInstruction(piData.target, piData.data || '')); } } // Element nodes (recursive) @@ -419,9 +421,9 @@ export class XMLToJSON { } /** - * Clean up any resources (especially for JSDOM) + * Clean up any resources */ public cleanup(): void { - this.domAdapter.cleanup(); + DOMEnvironment.cleanup(); } } \ No newline at end of file diff --git a/src/dom-adapter.ts b/src/dom-adapter.ts deleted file mode 100644 index 32e91b0..0000000 --- a/src/dom-adapter.ts +++ /dev/null @@ -1,195 +0,0 @@ -/** - * DOM Adapter for XMLToJSON - * Provides a unified interface for DOM operations across different environments. - */ -import { isNode, isBrowser } from './helpers'; -import { EnvironmentError } from './errors'; - -/** - * Interface for DOM implementation - */ -export interface DOMImplementation { - parser: any; - serializer: any; - document: any; - createDocument: () => Document; -} - -/** - * Creates a DOM implementation based on the environment or provided implementation - */ -export class DOMAdapter { - private _parser: any; - private _serializer: any; - private _document: any; - private _implementation: any; - private _jsdomInstance: any = null; - - /** - * Create a new DOMAdapter - * @param customImplementation Optional custom DOM implementation - */ - constructor(customImplementation?: DOMImplementation) { - if (customImplementation) { - // Use custom implementation if provided - this._parser = customImplementation.parser; - this._serializer = customImplementation.serializer; - this._document = customImplementation.document; - this._implementation = { - createDocument: customImplementation.createDocument - }; - } else if (isBrowser()) { - // Browser environment - this._parser = new DOMParser(); - this._serializer = new XMLSerializer(); - this._document = document; - this._implementation = document.implementation; - } else if (isNode()) { - // Try JSDOM first - try { - const { JSDOM } = require('jsdom'); - this._jsdomInstance = new JSDOM(''); - this._parser = new this._jsdomInstance.window.DOMParser(); - this._serializer = new this._jsdomInstance.window.XMLSerializer(); - this._document = this._jsdomInstance.window.document; - this._implementation = this._jsdomInstance.window.document.implementation; - } catch (jsdomError) { - // Fall back to xmldom if JSDOM isn't available - try { - const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom'); - this._parser = new DOMParser(); - this._serializer = new XMLSerializer(); - this._implementation = new DOMImplementation(); - this._document = this._implementation.createDocument(null, null, null); - } catch (xmldomError) { - throw new EnvironmentError( - "Node.js environment detected. Please install either 'jsdom' or '@xmldom/xmldom' package, or provide a custom DOM implementation." - ); - } - } - } else { - throw new EnvironmentError("Unsupported environment"); - } - } - - /** - * Get the DOMParser instance - */ - get parser() { - return this._parser; - } - - /** - * Get the XMLSerializer instance - */ - get serializer() { - return this._serializer; - } - - /** - * Get the Document instance - */ - get document() { - return this._document; - } - - /** - * Parse XML string to DOM - * @param xmlString XML string to parse - * @param mimeType MIME type for parsing (default: 'text/xml') - * @returns Parsed Document - */ - parseFromString(xmlString: string, mimeType: string = 'text/xml'): Document { - try { - return this._parser.parseFromString(xmlString, mimeType); - } catch (error) { - throw new Error(`XML parsing error: ${error instanceof Error ? error.message : String(error)}`); - } - } - - /** - * Serialize DOM to XML string - * @param doc Document to serialize - * @returns XML string - */ - serializeToString(doc: Document): string { - try { - return this._serializer.serializeToString(doc); - } catch (error) { - throw new Error(`XML serialization error: ${error instanceof Error ? error.message : String(error)}`); - } - } - - /** - * Create a new empty XML document - * @returns New Document - */ - createDocument(): Document { - return this._implementation.createDocument(null, null, null); - } - - /** - * Create a text node - * @param data Text content - * @returns Text node - */ - createTextNode(data: string): Text { - return this._document.createTextNode(data); - } - - /** - * Create a CDATA section - * @param data CDATA content - * @returns CDATASection node - */ - createCDATASection(data: string): CDATASection { - return this._document.createCDATASection(data); - } - - /** - * Create a comment node - * @param data Comment content - * @returns Comment node - */ - createComment(data: string): Comment { - return this._document.createComment(data); - } - - /** - * Create a processing instruction - * @param target Target - * @param data Processing instruction data - * @returns ProcessingInstruction node - */ - createProcessingInstruction(target: string, data: string): ProcessingInstruction { - return this._document.createProcessingInstruction(target, data); - } - - /** - * Create an element - * @param tagName Element tag name - * @returns Element - */ - createElement(tagName: string): Element { - return this._document.createElement(tagName); - } - - /** - * Create an element with namespace - * @param namespaceURI Namespace URI - * @param qualifiedName Qualified name (with prefix) - * @returns Element - */ - createElementNS(namespaceURI: string, qualifiedName: string): Element { - return this._document.createElementNS(namespaceURI, qualifiedName); - } - - /** - * Clean up any resources (especially for JSDOM) - */ - cleanup(): void { - if (this._jsdomInstance) { - this._jsdomInstance.window.close(); - } - } -} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 7db4a5c..5dacc31 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ import { XMLToJSON } from './XMLToJSON'; import { XMLParser } from './XMLParser'; import { XMLSerializerUtil } from './XMLSerializer'; -import { DOMAdapter, DOMImplementation } from './dom-adapter'; +import { DOMEnvironment } from './DOMAdapter'; import { XMLToJSONConfig } from './types'; import { DEFAULT_CONFIG } from './config'; import * as helpers from './helpers'; @@ -15,8 +15,7 @@ export { XMLToJSON, XMLParser, XMLSerializerUtil, - DOMAdapter, - DOMImplementation, + DOMEnvironment, XMLToJSONConfig, DEFAULT_CONFIG, helpers, From 84a73c7ea3242c2cc39aa43817e59aefc1c126fc Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 10:16:43 -0500 Subject: [PATCH 06/38] added preserve attribute option --- examples/browser-example.html | 8 + src/XMLParser.ts | 28 +-- src/XMLSerializer.ts | 5 +- src/XMLToJSON.ts | 383 ++++++++++++++++++++-------------- src/config.ts | 1 + src/types.ts | 65 +++--- 6 files changed, 279 insertions(+), 211 deletions(-) diff --git a/examples/browser-example.html b/examples/browser-example.html index 73ced05..87be286 100644 --- a/examples/browser-example.html +++ b/examples/browser-example.html @@ -116,6 +116,12 @@

Preservation Options

Preserve Text Nodes +
+ +
diff --git a/src/JSONUtil.ts b/src/JSONUtil.ts new file mode 100644 index 0000000..b8f91ee --- /dev/null +++ b/src/JSONUtil.ts @@ -0,0 +1,151 @@ +export class JSONUtil { + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * Automatically traverses into $children arrays and flattens results. + * + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + */ + static getPath( + obj: Record, + path: string, + fallback: any = undefined + ): any { + const segments = path.split("."); + let current: any = obj; + + for (const segment of segments) { + if (Array.isArray(current)) { + // Apply the segment to each array element and flatten results + const results = current + .map((item) => this.resolveSegment(item, segment)) + .flat() + .filter((v) => v !== undefined); + current = results.length > 0 ? results : undefined; + } else { + current = this.resolveSegment(current, segment); + } + + if (current === undefined) return fallback; + } + + // Collapse singleton arrays + if (Array.isArray(current) && current.length === 1) { + return current[0]; + } + + return current !== undefined ? current : fallback; + } + + /** + * Resolves a single path segment in the context of a JSON object. + * Falls back to searching $children for matching keys. + * + * @param obj The current object + * @param segment The path segment to resolve + */ + private static resolveSegment(obj: any, segment: string): any { + if (obj == null || typeof obj !== "object") return undefined; + + if (segment in obj) { + return obj[segment]; + } + + // Check $children for objects that contain the segment + const children = obj["$children"]; + if (Array.isArray(children)) { + const matches = children + .map((child) => (segment in child ? child[segment] : undefined)) + .filter((v) => v !== undefined); + return matches.length > 0 ? matches : undefined; + } + + return undefined; + } + + /** + * Converts a plain JSON object to the XML-like JSON structure. + * Optionally wraps the result in a root element with attributes and namespaces. + * + * @param obj Standard JSON object + * @param root Optional root element configuration (either a string or object with $ keys) + * @returns XML-like JSON object + */ + static fromJSONObject(obj: any, root?: any): any { + const wrappedObject = this.wrapObject(obj); + + if (typeof root === "string") { + // Root is a simple string: wrap result with this root tag + return { [root]: wrappedObject }; + } + + if (root && typeof root === "object") { + // Handle root with $ keys like $ns, $pre, $attrs + const elementName = root.name || "root"; // Default to "root" if no name is provided + const prefix = root.$pre || ""; + const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName; + + const result: any = { + [qualifiedName]: {}, + }; + + // Add $attrs to the root element if defined + if (root.$attrs && Array.isArray(root.$attrs)) { + result[qualifiedName].$attrs = root.$attrs; + } + + // Merge existing $children with the new generated children + const children = root.$children ? root.$children : []; + result[qualifiedName].$children = [ + ...children, + { [elementName]: wrappedObject }, + ]; + + // Add namespace and prefix if defined + if (root.$ns) { + result[qualifiedName].$ns = root.$ns; + } + + if (prefix && root.$ns) { + result[qualifiedName][`xmlns:${prefix}`] = root.$ns; + } + + return result; + } + + // Default behavior if no root is provided + return wrappedObject; + } + + private static wrapObject(value: any): any { + if ( + value === null || + typeof value === "string" || + typeof value === "number" || + typeof value === "boolean" + ) { + return { $val: value }; + } + + if (Array.isArray(value)) { + // For arrays, wrap each item and return as a $children-style array of repeated elements + return { + $children: value.map((item) => { + return this.wrapObject(item); + }), + }; + } + + if (typeof value === "object") { + // It's an object: wrap its properties in $children + const children = Object.entries(value).map(([key, val]) => ({ + [key]: this.wrapObject(val), + })); + + return { $children: children }; + } + + return undefined; // Fallback for unhandled types + } +} diff --git a/src/config.ts b/src/config.ts index c3acd67..d90f21f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -26,14 +26,14 @@ export const DEFAULT_CONFIG: XMLToJSONConfig = { }, propNames: { - namespace: "@ns", - prefix: "@prefix", - attributes: "@attrs", - value: "@val", - cdata: "@cdata", - comments: "@comments", - instruction: "@instruction", // Renamed from '@processing' - target: "@target", // Added for processing instruction target - children: "@children", + namespace: "$ns", + prefix: "$pre", + attributes: "$attr", + value: "$val", + cdata: "$cdata", + comments: "$cmnt", + instruction: "$pi", + target: "$trgt", + children: "$children", }, }; \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index ef54151..26ecd20 100644 --- a/src/types.ts +++ b/src/types.ts @@ -34,8 +34,8 @@ export interface XMLToJSONConfig { value: string; cdata: string; comments: string; - instruction: string; // Renamed from 'processing' - target: string; // Added for processing instruction target + instruction: string; + target: string; children: string; }; } From e2c5443232d9a478af0bd718fe8dd851a8894d85 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 13:01:17 -0500 Subject: [PATCH 11/38] added JSONUtil to index.ts --- src/index.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/index.ts b/src/index.ts index 5dacc31..e38dee1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,16 @@ /** * XMLToJSON Library - Main entry point */ -import { XMLToJSON } from './XMLToJSON'; -import { XMLParser } from './XMLParser'; -import { XMLSerializerUtil } from './XMLSerializer'; -import { DOMEnvironment } from './DOMAdapter'; -import { XMLToJSONConfig } from './types'; -import { DEFAULT_CONFIG } from './config'; -import * as helpers from './helpers'; -import * as errors from './errors'; +import { XMLToJSON } from "./XMLToJSON"; +import { XMLParser } from "./XMLParser"; +import { XMLSerializerUtil } from "./XMLSerializer"; +import { DOMEnvironment } from "./DOMAdapter"; +import { XMLToJSONConfig } from "./types"; +import { DEFAULT_CONFIG } from "./config"; +import { JSONUtil } from "./JSONUtil"; + +import * as helpers from "./helpers"; +import * as errors from "./errors"; // Re-export all classes and types export { @@ -18,8 +20,9 @@ export { DOMEnvironment, XMLToJSONConfig, DEFAULT_CONFIG, + JSONUtil, helpers, - errors + errors, }; -export default XMLToJSON; \ No newline at end of file +export default XMLToJSON; From f24cad878c8bce2093c4d968fa79b7b9957aa2b4 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 17:11:00 -0500 Subject: [PATCH 12/38] refactored project structure facade interface --- examples/browser-example.html | 65 ++- examples/simple-example.js | 63 +++ jest.config.js | 6 +- package.json | 21 +- rollup.config.js | 10 +- src/XJX.ts | 84 +++ src/XMLToJSON.ts | 546 -------------------- src/{ => core}/DOMAdapter.ts | 58 ++- src/{XMLSerializer.ts => core/JSONToXML.ts} | 166 ++---- src/{XMLParser.ts => core/XMLToJSON.ts} | 69 +-- src/{ => core/config}/config.ts | 6 +- src/core/types/errors.ts | 53 ++ src/{ => core/types}/types.ts | 4 +- src/{ => core/utils}/JSONUtil.ts | 77 ++- src/core/utils/XMLUtil.ts | 173 +++++++ src/errors.ts | 53 -- src/helpers.ts | 54 -- src/index.ts | 31 +- test/README.md | 59 +++ test/XJX.test.ts | 170 ++++++ test/core/DOMAdapter.test.js | 170 ++++++ test/core/utils/JSONUtil.test.js | 235 +++++++++ test/core/utils/XMLUtil.test.js | 159 ++++++ test/jest.setup.js | 40 ++ 24 files changed, 1476 insertions(+), 896 deletions(-) create mode 100644 examples/simple-example.js create mode 100644 src/XJX.ts delete mode 100644 src/XMLToJSON.ts rename src/{ => core}/DOMAdapter.ts (82%) rename src/{XMLSerializer.ts => core/JSONToXML.ts} (50%) rename src/{XMLParser.ts => core/XMLToJSON.ts} (78%) rename src/{ => core/config}/config.ts (83%) create mode 100644 src/core/types/errors.ts rename src/{ => core/types}/types.ts (90%) rename src/{ => core/utils}/JSONUtil.ts (69%) create mode 100644 src/core/utils/XMLUtil.ts delete mode 100644 src/errors.ts delete mode 100644 src/helpers.ts create mode 100644 test/README.md create mode 100644 test/XJX.test.ts create mode 100644 test/core/DOMAdapter.test.js create mode 100644 test/core/utils/JSONUtil.test.js create mode 100644 test/core/utils/XMLUtil.test.js create mode 100644 test/jest.setup.js diff --git a/examples/browser-example.html b/examples/browser-example.html index e2263a4..c98eef7 100644 --- a/examples/browser-example.html +++ b/examples/browser-example.html @@ -3,7 +3,7 @@ - XMLToJSON Browser Example + XJX Browser Example -

XMLToJSON Browser Example

+

XJX Browser Example

Configuration

@@ -177,7 +177,7 @@

Property Names

@@ -245,8 +245,7 @@

XML

- +
@@ -256,11 +255,11 @@

JSON

- + - + \ No newline at end of file diff --git a/examples/simple-example.js b/examples/simple-example.js new file mode 100644 index 0000000..2706965 --- /dev/null +++ b/examples/simple-example.js @@ -0,0 +1,63 @@ +// Simple example of using the XJX library +import { XJX } from '../dist/index.js'; + +// Sample XML string +const xmlString = ` + + + The Great Gatsby + F. Scott Fitzgerald + 1925 + + + + + To Kill a Mockingbird + Harper Lee + 1960 + + + +`; + +// Create an instance of XJX with default configuration +const xjx = new XJX(); + +// Convert XML to JSON +console.log('Converting XML to JSON...'); +const jsonObj = xjx.xmlToJson(xmlString); +console.log('JSON result:'); +console.log(JSON.stringify(jsonObj, null, 2)); + +// Using getPath to extract specific values +console.log('\nExtracting specific values using getPath:'); +const bookTitle = xjx.getPath(jsonObj, 'library.book.title.$val'); +console.log(`Book title: ${bookTitle}`); + +const bookYear = xjx.getPath(jsonObj, 'library.book.year.$val'); +console.log(`Book year: ${bookYear}`); + +const bookId = xjx.getPath(jsonObj, 'library.book.$attr.id.$val'); +console.log(`Book ID: ${bookId}`); + +// Convert JSON back to XML +console.log('\nConverting back to XML...'); +const newXml = xjx.jsonToXml(jsonObj); +console.log('XML result:'); +console.log(newXml); + +// Pretty print XML +console.log('\nPretty printing XML:'); +const prettyXml = xjx.prettyPrintXml(xmlString); +console.log(prettyXml); + +// Validate XML +console.log('\nValidating XML:'); +const validationResult = xjx.validateXML(xmlString); +console.log(`XML is valid: ${validationResult.isValid}`); +if (!validationResult.isValid) { + console.log(`Validation error: ${validationResult.message}`); +} + +// Clean up when done (important for Node.js environments) +xjx.cleanup(); \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 65a967a..da1153a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ const config = { preset: 'ts-jest/presets/default-esm', - testEnvironment: 'jsdom', + testEnvironment: 'jsdom', // Use jsdom for browser-like environment extensionsToTreatAsEsm: ['.ts'], moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', @@ -21,7 +21,7 @@ const config = { '!src/**/index.ts', ], testMatch: [ - '**/__tests__/**/*.ts?(x)', + '**/test/**/*.ts?(x)', // Look for tests in the test directory '**/?(*.)+(spec|test).ts?(x)' ], testPathIgnorePatterns: [ @@ -29,7 +29,7 @@ const config = { '/dist/' ], setupFilesAfterEnv: [ - '/jest.setup.js' + '/test/jest.setup.js' ] }; diff --git a/package.json b/package.json index b80cfd8..73a90ca 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { - "name": "xmltojson", + "name": "xjx", "version": "3.0.0", "description": "A modern ESM library for bidirectional XML to JSON conversion with namespace and node type support.", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", - "browser": "./dist/xmltojson.umd.js", - "unpkg": "./dist/xmltojson.min.js", + "browser": "./dist/xjx.umd.js", + "unpkg": "./dist/xjx.min.js", "types": "./dist/index.d.ts", "exports": { ".": { "import": "./dist/index.js", - "require": "./dist/xmltojson.umd.js", + "require": "./dist/xjx.umd.js", "types": "./dist/index.d.ts" } }, @@ -21,7 +21,7 @@ "README.md", "package.json" ], - "scripts": { +"scripts": { "clean": "rimraf dist", "build": "npm run clean && npm run build:types && npm run build:js", "build:types": "tsc --emitDeclarationOnly --outDir dist/dts", @@ -30,9 +30,10 @@ "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", + "test:ci": "jest --ci --coverage --reporters=default --reporters=jest-junit", "lint": "eslint ./src --ext .ts", "lint:fix": "eslint ./src --ext .ts --fix", - "format": "prettier --write \"src/**/*.ts\"", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "docs": "typedoc --out docs src/index.ts", "prepublishOnly": "npm run build:prod && npm run test", "preversion": "npm run lint", @@ -62,12 +63,12 @@ "license": "MIT", "repository": { "type": "git", - "url": "git+https://github.com/yourusername/xmltojson.git" + "url": "git+https://github.com/yourusername/xjx.git" }, "bugs": { - "url": "https://github.com/yourusername/xmltojson/issues" + "url": "https://github.com/yourusername/xjx/issues" }, - "homepage": "https://github.com/yourusername/xmltojson#readme", + "homepage": "https://github.com/yourusername/xjx#readme", "devDependencies": { "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-node-resolve": "^15.3.1", @@ -106,4 +107,4 @@ "engines": { "node": ">=14.16.0" } -} +} \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js index eca0015..2690562 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -26,7 +26,7 @@ const baseConfig = { }), visualizer({ filename: 'dist/stats.html', - title: 'XMLToJSON Bundle Visualizer', + title: 'XJX Bundle Visualizer', gzipSize: true, brotliSize: true, open: false // set to true to auto-open the report in browser @@ -50,9 +50,9 @@ export default [ { ...baseConfig, output: { - file: 'dist/xmltojson.umd.js', + file: 'dist/xjx.umd.js', format: 'umd', - name: 'XMLToJSON', + name: 'XJX', sourcemap: !isProd, exports: 'named', globals: { @@ -70,9 +70,9 @@ export default [ { ...baseConfig, output: { - file: 'dist/xmltojson.min.js', + file: 'dist/xjx.min.js', format: 'iife', - name: 'XMLToJSON', + name: 'XJX', sourcemap: !isProd, exports: 'named' }, diff --git a/src/XJX.ts b/src/XJX.ts new file mode 100644 index 0000000..ac7b893 --- /dev/null +++ b/src/XJX.ts @@ -0,0 +1,84 @@ +/** + * XJX - Facade class for XML-JSON conversion operations + */ +import { XMLToJSON } from "./core/XMLToJSON"; +import { JSONToXML } from "./core/JSONToXML"; +import { XMLToJSONConfig } from "./core/types/types"; +import { DEFAULT_CONFIG } from "./core/config/config"; +import { DOMAdapter } from "./core/DOMAdapter"; +import { XMLUtil } from "./core/utils/XMLUtil"; +import { JSONUtil } from "./core/utils/JSONUtil"; + +export class XJX { + private parser: XMLToJSON; + private serializer: JSONToXML; + private config: XMLToJSONConfig; + + /** + * Constructor for XJX utility + * @param config Configuration options + */ + constructor(config: Partial = {}) { + this.config = { ...DEFAULT_CONFIG, ...config }; + this.parser = new XMLToJSON(this.config); + this.serializer = new JSONToXML(this.config); + } + + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + public xmlToJson(xmlString: string): Record { + return this.parser.parse(xmlString); + } + + /** + * Convert JSON object back to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + public jsonToXml(jsonObj: Record): string { + return this.serializer.serialize(jsonObj); + } + + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + public prettyPrintXml(xmlString: string): string { + return XMLUtil.prettyPrintXml(xmlString, this.config.outputOptions.indent); + } + + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns The value at the specified path or the fallback value + */ + public getPath( + obj: Record, + path: string, + fallback: any = undefined + ): any { + return JSONUtil.getPath(obj, path, fallback); + } + + /** + * Validate XML string + * @param xmlString XML string to validate + * @returns Validation result + */ + public validateXML(xmlString: string): { isValid: boolean; message?: string } { + return XMLUtil.validateXML(xmlString); + } + + /** + * Clean up any resources + */ + public cleanup(): void { + DOMAdapter.cleanup(); + } +} \ No newline at end of file diff --git a/src/XMLToJSON.ts b/src/XMLToJSON.ts deleted file mode 100644 index 90c5b26..0000000 --- a/src/XMLToJSON.ts +++ /dev/null @@ -1,546 +0,0 @@ -/** - * XMLToJSON main class with hybrid DOM implementation support - */ -import { XMLToJSONConfig } from "./types"; -import { DEFAULT_CONFIG } from "./config"; -import { DOMEnvironment } from "./DOMAdapter"; - -/** - * XMLToJSON - Main class for XML to JSON transformation - * Supports both browser and Node.js environments - */ -export class XMLToJSON { - private config: XMLToJSONConfig; - - /** - * Constructor for XMLToJSON utility - * @param config Configuration options - */ - constructor(config: Partial = {}) { - this.config = { ...DEFAULT_CONFIG, ...config }; - } - - /** - * Convert XML string to JSON - * @param xmlString XML content as string - * @returns JSON object representing the XML content - */ - public xmlToJson(xmlString: string): Record { - try { - const xmlDoc = DOMEnvironment.parseFromString(xmlString, "text/xml"); - - // Check for parsing errors - const errors = xmlDoc.getElementsByTagName("parsererror"); - if (errors.length > 0) { - throw new Error(`XML parsing error: ${errors[0].textContent}`); - } - - return this.nodeToJson(xmlDoc.documentElement); - } catch (error) { - throw new Error( - `Failed to convert XML to JSON: ${ - error instanceof Error ? error.message : String(error) - }` - ); - } - } - - /** - * Convert JSON object back to XML string - * @param jsonObj JSON object to convert - * @returns XML string - */ - public jsonToXml(jsonObj: Record): string { - try { - const doc = DOMEnvironment.createDocument(); - const rootElement = this.jsonToNode(jsonObj, doc); - - if (rootElement) { - // Handle the temporary root element if it exists - if (doc.documentElement && doc.documentElement.nodeName === "temp") { - doc.replaceChild(rootElement, doc.documentElement); - } else { - doc.appendChild(rootElement); - } - } - - // Add XML declaration if specified - let xmlString = DOMEnvironment.serializeToString(doc); - if ( - this.config.outputOptions.xml.declaration && - !xmlString.startsWith("\n' + xmlString; - } - - // Apply pretty printing if enabled - if (this.config.outputOptions.prettyPrint) { - xmlString = this.prettyPrintXml(xmlString); - } - - return xmlString; - } catch (error) { - throw new Error( - `Failed to convert JSON to XML: ${ - error instanceof Error ? error.message : String(error) - }` - ); - } - } - - /** - * Convert a DOM node to JSON representation - * @param node DOM node to convert - * @returns JSON representation of the node - */ - private nodeToJson(node: Node): Record { - const result: Record = {}; - - // Handle element nodes - if (node.nodeType === DOMEnvironment.nodeTypes.ELEMENT_NODE) { - const element = node as Element; - // Use localName instead of nodeName to strip namespace prefix - const nodeName = - element.localName || - element.nodeName.split(":").pop() || - element.nodeName; - - const nodeObj: Record = {}; - - // Process namespaces if enabled - if (this.config.preserveNamespaces) { - const ns = element.namespaceURI; - if (ns) { - nodeObj[this.config.propNames.namespace] = ns; - } - - const prefix = element.prefix; - if (prefix) { - nodeObj[this.config.propNames.prefix] = prefix; - } - } - - // Process attributes if enabled - if (this.config.preserveAttributes && element.attributes.length > 0) { - const attrs: Array> = []; - - for (let i = 0; i < element.attributes.length; i++) { - const attr = element.attributes[i]; - // Strip namespace prefix from attribute name - const attrLocalName = - attr.localName || attr.name.split(":").pop() || attr.name; - - // Create attribute object with consistent structure - const attrObj: Record = { - [attrLocalName]: { - [this.config.propNames.value]: attr.value, - }, - }; - - // Add namespace info for attribute if present and enabled - if (this.config.preserveNamespaces) { - // Handle attribute namespace - if (attr.namespaceURI) { - attrObj[attrLocalName][this.config.propNames.namespace] = - attr.namespaceURI; - } - - // Handle attribute prefix - if (attr.prefix) { - attrObj[attrLocalName][this.config.propNames.prefix] = - attr.prefix; - } - } - - attrs.push(attrObj); - } - - if (attrs.length > 0) { - nodeObj[this.config.propNames.attributes] = attrs; - } - } - - // Process child nodes - if (element.childNodes.length > 0) { - const children: Array> = []; - - for (let i = 0; i < element.childNodes.length; i++) { - const child = element.childNodes[i]; - - // Text nodes - only process if preserveTextNodes is true - if (child.nodeType === DOMEnvironment.nodeTypes.TEXT_NODE) { - if (this.config.preserveTextNodes) { - const text = child.nodeValue || ""; - - // Skip whitespace-only text nodes if whitespace preservation is disabled - if (!this.config.preserveWhitespace && text.trim() === "") { - continue; - } - - children.push({ [this.config.propNames.value]: text }); - } - } - // CDATA sections - else if ( - child.nodeType === DOMEnvironment.nodeTypes.CDATA_SECTION_NODE && - this.config.preserveCDATA - ) { - children.push({ - [this.config.propNames.cdata]: child.nodeValue || "", - }); - } - // Comments - else if ( - child.nodeType === DOMEnvironment.nodeTypes.COMMENT_NODE && - this.config.preserveComments - ) { - children.push({ - [this.config.propNames.comments]: child.nodeValue || "", - }); - } - // Processing instructions - else if ( - child.nodeType === - DOMEnvironment.nodeTypes.PROCESSING_INSTRUCTION_NODE && - this.config.preserveProcessingInstr - ) { - children.push({ - [this.config.propNames.instruction]: { - [this.config.propNames.target]: child.nodeName, - [this.config.propNames.value]: child.nodeValue || "", - }, - }); - } - // Element nodes (recursive) - else if (child.nodeType === DOMEnvironment.nodeTypes.ELEMENT_NODE) { - children.push(this.nodeToJson(child)); - } - } - - if (children.length > 0) { - nodeObj[this.config.propNames.children] = children; - } - } - - // Apply compact option - remove empty properties if enabled - if (this.config.outputOptions.compact) { - Object.keys(nodeObj).forEach((key) => { - const cleaned = this.cleanNode(nodeObj[key]); - if (cleaned === undefined) { - delete nodeObj[key]; - } else { - nodeObj[key] = cleaned; - } - }); - } - - result[nodeName] = nodeObj; - } - - return result; - } - - private cleanNode(node: any): any { - if (Array.isArray(node)) { - // Clean each item in the array and filter out empty ones - const cleanedArray = node - .map((item) => this.cleanNode(item)) - .filter((item) => { - return !( - item === null || - item === undefined || - (typeof item === "object" && Object.keys(item).length === 0) - ); - }); - return cleanedArray.length > 0 ? cleanedArray : undefined; - } else if (typeof node === "object" && node !== null) { - // Clean properties recursively - Object.keys(node).forEach((key) => { - const cleanedChild = this.cleanNode(node[key]); - if ( - cleanedChild === null || - cleanedChild === undefined || - (Array.isArray(cleanedChild) && cleanedChild.length === 0) || - (typeof cleanedChild === "object" && - Object.keys(cleanedChild).length === 0) - ) { - delete node[key]; - } else { - node[key] = cleanedChild; - } - }); - - // Handle the special case for nodes with only empty children/attributes - const childrenKey = this.config.propNames.children; - const attrsKey = this.config.propNames.attributes; - const keys = Object.keys(node); - if ( - keys.every((key) => key === childrenKey || key === attrsKey) && - (node[childrenKey] === undefined || this.isEmpty(node[childrenKey])) && - (node[attrsKey] === undefined || this.isEmpty(node[attrsKey])) - ) { - return undefined; - } - - return Object.keys(node).length > 0 ? node : undefined; - } - - return node; - } - - private isEmpty(value: any): boolean { - if (value == null) return true; - if (Array.isArray(value)) return value.length === 0; - if (typeof value === "object") return Object.keys(value).length === 0; - return false; - } - - /** - * Convert JSON object to DOM node - * @param jsonObj JSON object to convert - * @param doc Document for creating elements - * @returns DOM Element - */ - private jsonToNode( - jsonObj: Record, - doc: Document - ): Element | null { - if (!jsonObj || typeof jsonObj !== "object") { - return null; - } - - // Get the node name (first key in the object) - const nodeName = Object.keys(jsonObj)[0]; - if (!nodeName) { - return null; - } - - const nodeData = jsonObj[nodeName]; - - // Create element with namespace if available - let element: Element; - const ns = nodeData[this.config.propNames.namespace]; - const prefix = nodeData[this.config.propNames.prefix]; - - if (ns && this.config.preserveNamespaces) { - if (prefix) { - // Create element with namespace and prefix - element = DOMEnvironment.createElementNS(ns, `${prefix}:${nodeName}`); - } else { - // Create element with namespace but no prefix - element = DOMEnvironment.createElementNS(ns, nodeName); - } - } else { - // Create element without namespace - element = DOMEnvironment.createElement(nodeName); - } - - // Process attributes if enabled - if ( - this.config.preserveAttributes && - nodeData[this.config.propNames.attributes] && - Array.isArray(nodeData[this.config.propNames.attributes]) - ) { - nodeData[this.config.propNames.attributes].forEach( - (attrObj: Record) => { - const attrName = Object.keys(attrObj)[0]; - if (!attrName) return; - - const attrData = attrObj[attrName]; - const attrValue = attrData[this.config.propNames.value] || ""; - const attrNs = attrData[this.config.propNames.namespace]; - const attrPrefix = attrData[this.config.propNames.prefix]; - - // Form qualified name for attribute if it has a prefix - let qualifiedName = attrName; - if (attrPrefix && this.config.preserveNamespaces) { - qualifiedName = `${attrPrefix}:${attrName}`; - } - - if (attrNs && this.config.preserveNamespaces) { - // Set attribute with namespace - element.setAttributeNS(attrNs, qualifiedName, attrValue); - } else { - // Set attribute without namespace - element.setAttribute(qualifiedName, attrValue); - } - } - ); - } - - // Process simple text value - if (nodeData[this.config.propNames.value] !== undefined) { - element.textContent = nodeData[this.config.propNames.value]; - } - - // Process children - if ( - nodeData[this.config.propNames.children] && - Array.isArray(nodeData[this.config.propNames.children]) - ) { - nodeData[this.config.propNames.children].forEach( - (child: Record) => { - // Text nodes - if ( - child[this.config.propNames.value] !== undefined && - this.config.preserveTextNodes - ) { - element.appendChild( - DOMEnvironment.createTextNode(child[this.config.propNames.value]) - ); - } - // CDATA sections - else if ( - child[this.config.propNames.cdata] !== undefined && - this.config.preserveCDATA - ) { - element.appendChild( - DOMEnvironment.createCDATASection( - child[this.config.propNames.cdata] - ) - ); - } - // Comments - else if ( - child[this.config.propNames.comments] !== undefined && - this.config.preserveComments - ) { - element.appendChild( - DOMEnvironment.createComment( - child[this.config.propNames.comments] - ) - ); - } - // Processing instructions - else if ( - child[this.config.propNames.instruction] !== undefined && - this.config.preserveProcessingInstr - ) { - const piData = child[this.config.propNames.instruction]; - const target = piData[this.config.propNames.target]; - const data = piData[this.config.propNames.value] || ""; - - if (target) { - element.appendChild( - DOMEnvironment.createProcessingInstruction(target, data) - ); - } - } - // Element nodes (recursive) - else { - const childElement = this.jsonToNode(child, doc); - if (childElement) { - element.appendChild(childElement); - } - } - } - ); - } - - return element; - } - - /** - * Apply simple pretty printing to XML string - * @param xmlString XML string to format - * @returns Formatted XML string - */ - private prettyPrintXml(xmlString: string): string { - // This is a simple implementation - // A production-ready solution would use a proper XML formatter - let formatted = ""; - let indent = 0; - const indentString = " ".repeat(this.config.outputOptions.indent); - - // Simple state machine for XML formatting - let inTag = false; - let inContent = false; - let inCDATA = false; - let inComment = false; - - for (let i = 0; i < xmlString.length; i++) { - const char = xmlString.charAt(i); - const nextChar = xmlString.charAt(i + 1); - - // Handle CDATA sections - if (char === "<" && xmlString.substr(i, 9) === "") { - inCDATA = false; - formatted += "]]>"; - i += 2; - continue; - } - if (inCDATA) { - formatted += char; - continue; - } - - // Handle comments - if (char === "<" && xmlString.substr(i, 4) === "") { - inComment = false; - formatted += "-->"; - i += 2; - continue; - } - if (inComment) { - formatted += char; - continue; - } - - // Handle tags and content - if (char === "<" && !inTag && !inContent) { - // Check if it's a closing tag - if (nextChar === "/") { - indent -= 1; - } - - if (!inContent) { - formatted += "\n" + indentString.repeat(indent); - } - - formatted += char; - inTag = true; - inContent = false; - } else if (char === ">" && inTag) { - formatted += char; - inTag = false; - - // Check if it's a self-closing tag - if (xmlString.charAt(i - 1) !== "/") { - inContent = true; - } - - // Check if it's an opening tag (not self-closing) - if ( - xmlString.charAt(i - 1) !== "/" && - xmlString.charAt(i - 1) !== "?" - ) { - indent += 1; - } - } else if (inContent && char === "<" && nextChar !== "!") { - inContent = false; - i--; // Re-process this character as a tag start - } else { - formatted += char; - } - } - - return formatted; - } - - /** - * Clean up any resources - */ - public cleanup(): void { - DOMEnvironment.cleanup(); - } -} diff --git a/src/DOMAdapter.ts b/src/core/DOMAdapter.ts similarity index 82% rename from src/DOMAdapter.ts rename to src/core/DOMAdapter.ts index d3de021..d3d98a1 100644 --- a/src/DOMAdapter.ts +++ b/src/core/DOMAdapter.ts @@ -1,7 +1,7 @@ /** * DOM Environment provider with unified interface for browser and Node.js */ -import { XMLToJSONError } from './errors'; +import { XMLToJSONError } from './types/errors'; interface NodeTypes { ELEMENT_NODE: number; @@ -29,7 +29,7 @@ interface JSDOMInstance { window: DOMWindow; } -export const DOMEnvironment = (() => { +export const DOMAdapter = (() => { // Environment-specific DOM implementation let domParser: any; let xmlSerializer: any; @@ -233,6 +233,60 @@ export const DOMEnvironment = (() => { } }, + // New helper methods + + /** + * Creates a proper namespace qualified attribute + */ + setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => { + try { + if (namespaceURI) { + element.setAttributeNS(namespaceURI, qualifiedName, value); + } else { + element.setAttribute(qualifiedName, value); + } + } catch (error) { + throw new XMLToJSONError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + /** + * Check if an object is a DOM node + */ + isNode: (obj: any): boolean => { + try { + return obj && typeof obj === 'object' && typeof obj.nodeType === 'number'; + } catch (error) { + return false; + } + }, + + /** + * Get DOM node type as string for debugging + */ + getNodeTypeName: (nodeType: number): string => { + switch (nodeType) { + case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE'; + case nodeTypes.TEXT_NODE: return 'TEXT_NODE'; + case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE'; + case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE'; + case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE'; + default: return `UNKNOWN_NODE_TYPE(${nodeType})`; + } + }, + + /** + * Get all node attributes as an object + */ + getNodeAttributes: (node: Element): Record => { + const result: Record = {}; + for (let i = 0; i < node.attributes.length; i++) { + const attr = node.attributes[i]; + result[attr.name] = attr.value; + } + return result; + }, + // Cleanup method (mainly for JSDOM) cleanup: () => { if (jsdomInstance && typeof jsdomInstance.window.close === 'function') { diff --git a/src/XMLSerializer.ts b/src/core/JSONToXML.ts similarity index 50% rename from src/XMLSerializer.ts rename to src/core/JSONToXML.ts index 6870cf0..b53fa64 100644 --- a/src/XMLSerializer.ts +++ b/src/core/JSONToXML.ts @@ -1,33 +1,23 @@ /** - * XMLSerializer class for converting JSON to XML with consistent namespace handling + * JSONToXML class for converting JSON to XML with consistent namespace handling */ -import { XMLToJSONConfig } from "./types"; -import { DEFAULT_CONFIG } from "./config"; -import { DOMEnvironment } from './DOMAdapter'; +import { XMLToJSONConfig } from "./types/types"; +import { XMLToJSONError } from "./types/errors"; +import { DOMAdapter } from "./DOMAdapter"; +import { XMLUtil } from "./utils/XMLUtil"; /** - * XML Serializer for converting JSON to XML + * JSONToXML for converting JSON to XML */ -export class XMLSerializerUtil { +export class JSONToXML { private config: XMLToJSONConfig; - private serializer: XMLSerializer | null = null; /** - * Constructor for XMLSerializer + * Constructor for JSONToXML * @param config Configuration options */ - constructor(config: Partial = {}) { - this.config = { ...DEFAULT_CONFIG, ...config }; - - // Initialize serializer for browser environment - if (typeof window !== "undefined") { - this.serializer = new XMLSerializer(); - } else { - // Node.js environment - dynamically import would be needed - throw new Error( - "Node.js environment detected. You need to use a Node-compatible XML serializer." - ); - } + constructor(config: XMLToJSONConfig) { + this.config = config; } /** @@ -36,35 +26,33 @@ export class XMLSerializerUtil { * @returns XML string */ public serialize(jsonObj: Record): string { - if (!this.serializer) { - throw new Error("XML serializer not initialized"); - } - try { - const doc = document.implementation.createDocument(null, null, null); + const doc = DOMAdapter.createDocument(); const rootElement = this.jsonToNode(jsonObj, doc); if (rootElement) { - doc.appendChild(rootElement); + // Handle the temporary root element if it exists + if (doc.documentElement && doc.documentElement.nodeName === "temp") { + doc.replaceChild(rootElement, doc.documentElement); + } else { + doc.appendChild(rootElement); + } } // Add XML declaration if specified - let xmlString = this.serializer.serializeToString(doc); - if ( - this.config.outputOptions.xml.declaration && - !xmlString.startsWith("\n' + xmlString; + let xmlString = DOMAdapter.serializeToString(doc); + if (this.config.outputOptions.xml.declaration) { + xmlString = XMLUtil.ensureXMLDeclaration(xmlString); } // Apply pretty printing if enabled if (this.config.outputOptions.prettyPrint) { - xmlString = this.prettyPrintXml(xmlString); + xmlString = XMLUtil.prettyPrintXml(xmlString, this.config.outputOptions.indent); } return xmlString; } catch (error) { - throw new Error( + throw new XMLToJSONError( `Failed to convert JSON to XML: ${ error instanceof Error ? error.message : String(error) }` @@ -102,17 +90,17 @@ export class XMLSerializerUtil { if (ns && this.config.preserveNamespaces) { if (prefix) { // Create element with namespace and prefix - element = doc.createElementNS(ns, `${prefix}:${nodeName}`); + element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`); } else { // Create element with namespace but no prefix - element = doc.createElementNS(ns, nodeName); + element = DOMAdapter.createElementNS(ns, nodeName); } } else { // Create element without namespace - element = doc.createElement(nodeName); + element = DOMAdapter.createElement(nodeName); } - // Process attributes with consistent namespace handling if enabled + // Process attributes if enabled if ( this.config.preserveAttributes && nodeData[this.config.propNames.attributes] && @@ -134,13 +122,12 @@ export class XMLSerializerUtil { qualifiedName = `${attrPrefix}:${attrName}`; } - if (attrNs && this.config.preserveNamespaces) { - // Set attribute with namespace - element.setAttributeNS(attrNs, qualifiedName, attrValue); - } else { - // Set attribute without namespace - element.setAttribute(qualifiedName, attrValue); - } + DOMAdapter.setNamespacedAttribute( + element, + (attrNs && this.config.preserveNamespaces) ? attrNs : null, + qualifiedName, + attrValue + ); } ); } @@ -163,7 +150,7 @@ export class XMLSerializerUtil { this.config.preserveTextNodes ) { element.appendChild( - doc.createTextNode(child[this.config.propNames.value]) + DOMAdapter.createTextNode(child[this.config.propNames.value]) ); } // CDATA sections @@ -172,7 +159,9 @@ export class XMLSerializerUtil { this.config.preserveCDATA ) { element.appendChild( - doc.createCDATASection(child[this.config.propNames.cdata]) + DOMAdapter.createCDATASection( + child[this.config.propNames.cdata] + ) ); } // Comments @@ -181,7 +170,9 @@ export class XMLSerializerUtil { this.config.preserveComments ) { element.appendChild( - doc.createComment(child[this.config.propNames.comments]) + DOMAdapter.createComment( + child[this.config.propNames.comments] + ) ); } // Processing instructions @@ -191,11 +182,11 @@ export class XMLSerializerUtil { ) { const piData = child[this.config.propNames.instruction]; const target = piData[this.config.propNames.target]; - const data = piData[this.config.propNames.value] || ''; - + const data = piData[this.config.propNames.value] || ""; + if (target) { element.appendChild( - doc.createProcessingInstruction(target, data) + DOMAdapter.createProcessingInstruction(target, data) ); } } @@ -212,77 +203,4 @@ export class XMLSerializerUtil { return element; } - - /** - * Pretty print an XML string - * @param xmlString XML string to format - * @returns Formatted XML string - */ - private prettyPrintXml(xmlString: string): string { - const INDENT = - typeof this.config.outputOptions.indent === "number" - ? " ".repeat(this.config.outputOptions.indent) - : " "; - - const doc = DOMEnvironment.parseFromString(xmlString, 'text/xml'); - - const serializer = (node: Node, level = 0): string => { - const pad = INDENT.repeat(level); - - switch (node.nodeType) { - case Node.ELEMENT_NODE: { - const el = node as Element; - const tagName = el.tagName; - const attrs = Array.from(el.attributes) - .map((a) => `${a.name}="${a.value}"`) - .join(" "); - const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`; - - const children = Array.from(el.childNodes); - if (children.length === 0) { - return `${pad}${openTag.replace(/>$/, " />")}\n`; - } - - // Single text node: print inline - if ( - children.length === 1 && - children[0].nodeType === Node.TEXT_NODE && - children[0].textContent?.trim() !== "" - ) { - return `${pad}${openTag}${children[0].textContent}\n`; - } - - const inner = children - .map((child) => serializer(child, level + 1)) - .join(""); - return `${pad}${openTag}\n${inner}${pad}\n`; - } - - case Node.TEXT_NODE: { - const text = node.textContent?.trim(); - return text ? `${pad}${text}\n` : ""; - } - - case Node.CDATA_SECTION_NODE: - return `${pad}\n`; - - case Node.COMMENT_NODE: - return `${pad}\n`; - - case Node.PROCESSING_INSTRUCTION_NODE: - const pi = node as ProcessingInstruction; - return `${pad}\n`; - - case Node.DOCUMENT_NODE: - return Array.from(node.childNodes) - .map((child) => serializer(child, level)) - .join(""); - - default: - return ""; - } - }; - - return serializer(doc).trim(); - } } \ No newline at end of file diff --git a/src/XMLParser.ts b/src/core/XMLToJSON.ts similarity index 78% rename from src/XMLParser.ts rename to src/core/XMLToJSON.ts index 64a6dd7..6144c6f 100644 --- a/src/XMLParser.ts +++ b/src/core/XMLToJSON.ts @@ -1,32 +1,23 @@ /** - * XMLParser class for converting XML to JSON with consistent namespace handling + * XMLToJSON class for converting XML to JSON with consistent namespace handling */ -import { XMLToJSONConfig } from "./types"; -import { DEFAULT_CONFIG } from "./config"; +import { XMLToJSONConfig } from "./types/types"; +import { XMLToJSONError } from "./types/errors"; +import { DOMAdapter } from "./DOMAdapter"; +import { JSONUtil } from "./utils/JSONUtil"; /** - * XML Parser for converting XML to JSON + * XMLToJSON Parser for converting XML to JSON */ -export class XMLParser { +export class XMLToJSON { private config: XMLToJSONConfig; - private parser: DOMParser | null = null; /** - * Constructor for XMLParser + * Constructor for XMLToJSON * @param config Configuration options */ - constructor(config: Partial = {}) { - this.config = { ...DEFAULT_CONFIG, ...config }; - - // Initialize parser for browser environment - if (typeof window !== "undefined") { - this.parser = new DOMParser(); - } else { - // Node.js environment - dynamically import would be needed - throw new Error( - "Node.js environment detected. You need to use a Node-compatible XML parser." - ); - } + constructor(config: XMLToJSONConfig) { + this.config = config; } /** @@ -35,22 +26,18 @@ export class XMLParser { * @returns JSON object representing the XML content */ public parse(xmlString: string): Record { - if (!this.parser) { - throw new Error("XML parser not initialized"); - } - try { - const xmlDoc = this.parser.parseFromString(xmlString, "text/xml"); + const xmlDoc = DOMAdapter.parseFromString(xmlString, "text/xml"); // Check for parsing errors - const parserError = xmlDoc.querySelector("parsererror"); - if (parserError) { - throw new Error(`XML parsing error: ${parserError.textContent}`); + const errors = xmlDoc.getElementsByTagName("parsererror"); + if (errors.length > 0) { + throw new XMLToJSONError(`XML parsing error: ${errors[0].textContent}`); } return this.nodeToJson(xmlDoc.documentElement); } catch (error) { - throw new Error( + throw new XMLToJSONError( `Failed to convert XML to JSON: ${ error instanceof Error ? error.message : String(error) }` @@ -67,7 +54,7 @@ export class XMLParser { const result: Record = {}; // Handle element nodes - if (node.nodeType === Node.ELEMENT_NODE) { + if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { const element = node as Element; // Use localName instead of nodeName to strip namespace prefix const nodeName = @@ -138,7 +125,7 @@ export class XMLParser { const child = element.childNodes[i]; // Text nodes - only process if preserveTextNodes is true - if (child.nodeType === Node.TEXT_NODE) { + if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) { if (this.config.preserveTextNodes) { const text = child.nodeValue || ""; @@ -152,7 +139,7 @@ export class XMLParser { } // CDATA sections else if ( - child.nodeType === Node.CDATA_SECTION_NODE && + child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE && this.config.preserveCDATA ) { children.push({ @@ -161,7 +148,7 @@ export class XMLParser { } // Comments else if ( - child.nodeType === Node.COMMENT_NODE && + child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE && this.config.preserveComments ) { children.push({ @@ -170,7 +157,8 @@ export class XMLParser { } // Processing instructions else if ( - child.nodeType === Node.PROCESSING_INSTRUCTION_NODE && + child.nodeType === + DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE && this.config.preserveProcessingInstr ) { children.push({ @@ -181,7 +169,7 @@ export class XMLParser { }); } // Element nodes (recursive) - else if (child.nodeType === Node.ELEMENT_NODE) { + else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { children.push(this.nodeToJson(child)); } } @@ -245,8 +233,8 @@ export class XMLParser { const keys = Object.keys(node); if ( keys.every((key) => key === childrenKey || key === attrsKey) && - (node[childrenKey] === undefined || this.isEmpty(node[childrenKey])) && - (node[attrsKey] === undefined || this.isEmpty(node[attrsKey])) + (node[childrenKey] === undefined || JSONUtil.isEmpty(node[childrenKey])) && + (node[attrsKey] === undefined || JSONUtil.isEmpty(node[attrsKey])) ) { return undefined; } @@ -256,11 +244,4 @@ export class XMLParser { return node; } - - private isEmpty(value: any): boolean { - if (value == null) return true; - if (Array.isArray(value)) return value.length === 0; - if (typeof value === "object") return Object.keys(value).length === 0; - return false; - } -} +} \ No newline at end of file diff --git a/src/config.ts b/src/core/config/config.ts similarity index 83% rename from src/config.ts rename to src/core/config/config.ts index d90f21f..2d0e458 100644 --- a/src/config.ts +++ b/src/core/config/config.ts @@ -1,10 +1,10 @@ /** - * Default configuration for XMLToJSON + * Default configuration for the XJX library */ -import { XMLToJSONConfig } from './types'; +import { XMLToJSONConfig } from '../types/types'; /** - * Default configuration for XMLToJSON + * Default configuration */ export const DEFAULT_CONFIG: XMLToJSONConfig = { preserveNamespaces: true, diff --git a/src/core/types/errors.ts b/src/core/types/errors.ts new file mode 100644 index 0000000..24bd07e --- /dev/null +++ b/src/core/types/errors.ts @@ -0,0 +1,53 @@ +/** + * Error classes for the XJX library + */ + +/** + * Base error class + */ +export class XMLToJSONError extends Error { + constructor(message: string) { + super(message); + this.name = 'XMLToJSONError'; + } +} + +/** + * Error for XML parsing issues + */ +export class XMLParseError extends XMLToJSONError { + constructor(message: string) { + super(`XML parse error: ${message}`); + this.name = 'XMLParseError'; + } +} + +/** + * Error for XML serialization issues + */ +export class XMLSerializeError extends XMLToJSONError { + constructor(message: string) { + super(`XML serialize error: ${message}`); + this.name = 'XMLSerializeError'; + } +} + +/** + * Error for environment incompatibility + */ +export class EnvironmentError extends XMLToJSONError { + constructor(message: string) { + super(`Environment error: ${message}`); + this.name = 'EnvironmentError'; + } +} + +/** + * Error for invalid configuration + */ +export class ConfigurationError extends XMLToJSONError { + constructor(message: string) { + super(`Configuration error: ${message}`); + this.name = 'ConfigurationError'; + } +} \ No newline at end of file diff --git a/src/types.ts b/src/core/types/types.ts similarity index 90% rename from src/types.ts rename to src/core/types/types.ts index 26ecd20..89867ad 100644 --- a/src/types.ts +++ b/src/core/types/types.ts @@ -1,9 +1,9 @@ /** - * Type definitions for XMLToJSON + * Type definitions for the XJX library */ /** - * Configuration interface for XMLToJSON + * Configuration interface for the library */ export interface XMLToJSONConfig { // Features to preserve during transformation diff --git a/src/JSONUtil.ts b/src/core/utils/JSONUtil.ts similarity index 69% rename from src/JSONUtil.ts rename to src/core/utils/JSONUtil.ts index b8f91ee..7952d17 100644 --- a/src/JSONUtil.ts +++ b/src/core/utils/JSONUtil.ts @@ -1,3 +1,6 @@ +/** + * JSONUtil - Utility functions for JSON processing + */ export class JSONUtil { /** * Safely retrieves a value from a JSON object using a dot-separated path. @@ -6,6 +9,7 @@ export class JSONUtil { * @param obj The input JSON object * @param path The dot-separated path string (e.g., "root.item.description.$val") * @param fallback Value to return if the path does not resolve + * @returns Retrieved value or fallback */ static getPath( obj: Record, @@ -44,6 +48,7 @@ export class JSONUtil { * * @param obj The current object * @param segment The path segment to resolve + * @returns Resolved value or undefined */ private static resolveSegment(obj: any, segment: string): any { if (obj == null || typeof obj !== "object") return undefined; @@ -118,6 +123,11 @@ export class JSONUtil { return wrappedObject; } + /** + * Wraps a standard JSON value in the XML-like JSON structure + * @param value Value to wrap + * @returns Wrapped value + */ private static wrapObject(value: any): any { if ( value === null || @@ -148,4 +158,69 @@ export class JSONUtil { return undefined; // Fallback for unhandled types } -} + + /** + * Check if an object is empty + * @param value Value to check + * @returns true if empty + */ + static isEmpty(value: any): boolean { + if (value == null) return true; + if (Array.isArray(value)) return value.length === 0; + if (typeof value === 'object') return Object.keys(value).length === 0; + return false; + } + + /** + * Safely stringify JSON for debugging + * @param obj Object to stringify + * @param indent Optional indentation level + * @returns JSON string representation + */ + static safeStringify(obj: any, indent: number = 2): string { + try { + return JSON.stringify(obj, null, indent); + } catch (error) { + return '[Cannot stringify object]'; + } + } + + /** + * Deep clone an object + * @param obj Object to clone + * @returns Cloned object + */ + static deepClone(obj: any): any { + try { + return JSON.parse(JSON.stringify(obj)); + } catch (error) { + throw new Error(`Failed to deep clone object: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Deep merge two objects + * @param target Target object + * @param source Source object + * @returns Merged object (target is modified) + */ + static deepMerge(target: any, source: any): any { + if (typeof source !== 'object' || source === null) { + return target; + } + + if (typeof target !== 'object' || target === null) { + return this.deepClone(source); + } + + Object.keys(source).forEach(key => { + if (source[key] instanceof Object && key in target && target[key] instanceof Object) { + this.deepMerge(target[key], source[key]); + } else { + target[key] = this.deepClone(source[key]); + } + }); + + return target; + } +} \ No newline at end of file diff --git a/src/core/utils/XMLUtil.ts b/src/core/utils/XMLUtil.ts new file mode 100644 index 0000000..77e898b --- /dev/null +++ b/src/core/utils/XMLUtil.ts @@ -0,0 +1,173 @@ +/** + * XMLUtil - Utility functions for XML processing + */ +import { XMLToJSONError } from "../types/errors"; +import { DOMAdapter } from "../DOMAdapter"; + +export class XMLUtil { + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @param indent Number of spaces for indentation + * @returns Formatted XML string + */ + static prettyPrintXml(xmlString: string, indent: number = 2): string { + const INDENT = " ".repeat(indent); + + try { + const doc = DOMAdapter.parseFromString(xmlString, 'text/xml'); + + const serializer = (node: Node, level = 0): string => { + const pad = INDENT.repeat(level); + + switch (node.nodeType) { + case DOMAdapter.nodeTypes.ELEMENT_NODE: { + const el = node as Element; + const tagName = el.tagName; + const attrs = Array.from(el.attributes) + .map((a) => `${a.name}="${a.value}"`) + .join(" "); + const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`; + + const children = Array.from(el.childNodes); + if (children.length === 0) { + return `${pad}${openTag.replace(/>$/, " />")}\n`; + } + + // Single text node: print inline + if ( + children.length === 1 && + children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE && + children[0].textContent?.trim() !== "" + ) { + return `${pad}${openTag}${children[0].textContent}\n`; + } + + const inner = children + .map((child) => serializer(child, level + 1)) + .join(""); + return `${pad}${openTag}\n${inner}${pad}\n`; + } + + case DOMAdapter.nodeTypes.TEXT_NODE: { + const text = node.textContent?.trim(); + return text ? `${pad}${text}\n` : ""; + } + + case DOMAdapter.nodeTypes.CDATA_SECTION_NODE: + return `${pad}\n`; + + case DOMAdapter.nodeTypes.COMMENT_NODE: + return `${pad}\n`; + + case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE: + const pi = node as ProcessingInstruction; + return `${pad}\n`; + + case DOMAdapter.nodeTypes.DOCUMENT_NODE: + return Array.from(node.childNodes) + .map((child) => serializer(child, level)) + .join(""); + + default: + return ""; + } + }; + + return serializer(doc).trim(); + } catch (error) { + throw new XMLToJSONError(`Failed to pretty print XML: ${error instanceof Error ? error.message : String(error)}`); + } + } + + /** + * Check if XML string is well-formed + * @param xmlString XML string to validate + * @returns Object with validation result and any error messages + */ + static validateXML(xmlString: string): { isValid: boolean; message?: string } { + try { + const doc = DOMAdapter.parseFromString(xmlString, "text/xml"); + const errors = doc.getElementsByTagName("parsererror"); + if (errors.length > 0) { + return { isValid: false, message: errors[0].textContent || "Unknown parsing error" }; + } + return { isValid: true }; + } catch (error) { + return { + isValid: false, + message: error instanceof Error ? error.message : String(error) + }; + } + } + + /** + * Add XML declaration to a string if missing + * @param xmlString XML string + * @returns XML string with declaration + */ + static ensureXMLDeclaration(xmlString: string): string { + if (!xmlString.trim().startsWith('\n' + xmlString; + } + return xmlString; + } + + /** + * Escape special XML characters + * @param text Text to escape + * @returns Escaped text + */ + static escapeXML(text: string): string { + return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + /** + * Unescape XML entities + * @param text Text with XML entities + * @returns Unescaped text + */ + static unescapeXML(text: string): string { + return text + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, "'"); + } + + /** + * Extract the namespace prefix from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Prefix or null if no prefix + */ + static extractPrefix(qualifiedName: string): string | null { + const colonIndex = qualifiedName.indexOf(':'); + return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null; + } + + /** + * Extract the local name from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Local name + */ + static extractLocalName(qualifiedName: string): string { + const colonIndex = qualifiedName.indexOf(':'); + return colonIndex > 0 ? qualifiedName.substring(colonIndex + 1) : qualifiedName; + } + + /** + * Create a qualified name from prefix and local name + * @param prefix Namespace prefix (can be null) + * @param localName Local name + * @returns Qualified name + */ + static createQualifiedName(prefix: string | null, localName: string): string { + return prefix ? `${prefix}:${localName}` : localName; + } +} \ No newline at end of file diff --git a/src/errors.ts b/src/errors.ts deleted file mode 100644 index 02fb063..0000000 --- a/src/errors.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Error classes for XMLToJSON - */ - -/** - * Base error class for XMLToJSON - */ -export class XMLToJSONError extends Error { - constructor(message: string) { - super(message); - this.name = 'XMLToJSONError'; - } - } - - /** - * Error for XML parsing issues - */ - export class XMLParseError extends XMLToJSONError { - constructor(message: string) { - super(`XML parse error: ${message}`); - this.name = 'XMLParseError'; - } - } - - /** - * Error for XML serialization issues - */ - export class XMLSerializeError extends XMLToJSONError { - constructor(message: string) { - super(`XML serialize error: ${message}`); - this.name = 'XMLSerializeError'; - } - } - - /** - * Error for environment incompatibility - */ - export class EnvironmentError extends XMLToJSONError { - constructor(message: string) { - super(`Environment error: ${message}`); - this.name = 'EnvironmentError'; - } - } - - /** - * Error for invalid configuration - */ - export class ConfigurationError extends XMLToJSONError { - constructor(message: string) { - super(`Configuration error: ${message}`); - this.name = 'ConfigurationError'; - } - } \ No newline at end of file diff --git a/src/helpers.ts b/src/helpers.ts deleted file mode 100644 index 83ca276..0000000 --- a/src/helpers.ts +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Helper functions for XMLToJSON - */ - -/** - * Determines if the current environment is a browser - * @returns true if running in browser, false otherwise - */ -export const isBrowser = (): boolean => { - return typeof window !== 'undefined' && typeof window.document !== 'undefined'; - }; - - /** - * Determines if the current environment is Node.js - * @returns true if running in Node.js, false otherwise - */ - export const isNode = (): boolean => { - return typeof process !== 'undefined' && - process.versions != null && - process.versions.node != null; - }; - - /** - * Check if an object is empty - * @param obj Object to check - * @returns true if object is empty, false otherwise - */ - export const isEmptyObject = (obj: any): boolean => { - if (!obj) return true; - if (typeof obj !== 'object') return false; - if (Array.isArray(obj)) return obj.length === 0; - return Object.keys(obj).length === 0; - }; - - /** - * Safely stringify JSON for debugging - * @param obj Object to stringify - * @param indent Optional indentation level - * @returns JSON string representation - */ - export const safeStringify = (obj: any, indent: number = 2): string => { - try { - return JSON.stringify(obj, null, indent); - } catch (error) { - return '[Cannot stringify object]'; - } - }; - - export default { - isBrowser, - isNode, - isEmptyObject, - safeStringify - }; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index e38dee1..38d5507 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,28 +1,29 @@ /** - * XMLToJSON Library - Main entry point + * XJX Library - Main entry point */ -import { XMLToJSON } from "./XMLToJSON"; -import { XMLParser } from "./XMLParser"; -import { XMLSerializerUtil } from "./XMLSerializer"; -import { DOMEnvironment } from "./DOMAdapter"; -import { XMLToJSONConfig } from "./types"; -import { DEFAULT_CONFIG } from "./config"; -import { JSONUtil } from "./JSONUtil"; +import { XJX } from "./XJX"; +import { XMLToJSON } from "./core/XMLToJSON"; +import { JSONToXML } from "./core/JSONToXML"; +import { DOMAdapter } from "./core/DOMAdapter"; +import { XMLToJSONConfig } from "./core/types/types"; +import { DEFAULT_CONFIG } from "./core/config/config"; +import { JSONUtil } from "./core/utils/JSONUtil"; +import { XMLUtil } from "./core/utils/XMLUtil"; -import * as helpers from "./helpers"; -import * as errors from "./errors"; +import * as errors from "./core/types/errors"; // Re-export all classes and types export { + XJX, XMLToJSON, - XMLParser, - XMLSerializerUtil, - DOMEnvironment, + JSONToXML, + DOMAdapter, XMLToJSONConfig, DEFAULT_CONFIG, JSONUtil, - helpers, + XMLUtil, errors, }; -export default XMLToJSON; +// Default export for easier importing +export default XJX; \ No newline at end of file diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..dbd8190 --- /dev/null +++ b/test/README.md @@ -0,0 +1,59 @@ +# XJX Library Tests + +This directory contains tests for the XJX library. The tests are written using Jest and run in a JSDOM environment to simulate browser behavior. + +## Test Structure + +- `XJX.test.ts` - Tests for the main facade class +- `utils/XMLUtil.test.ts` - Tests for XML utility functions +- `utils/JSONUtil.test.ts` - Tests for JSON utility functions +- `jest.setup.js` - Setup file for Jest testing environment + +## Running Tests + +To run the tests, use one of the following commands: + +```bash +# Run all tests +npm test + +# Run tests in watch mode (useful during development) +npm run test:watch + +# Generate coverage report +npm run test:coverage +``` + +## Writing Tests + +When writing tests for the XJX library, consider the following: + +1. Tests should be placed in this `/test` directory, mirroring the structure of the `/src` directory +2. Each test file should focus on testing a single class or module +3. Use descriptive test names following the pattern: `it('should do something when something happens')` +4. Use the JSDOM environment to test browser-specific functionality +5. Clean up resources after each test to prevent memory leaks + +## Test Environment + +The tests run in a JSDOM environment, which provides browser-like globals such as `window`, `document`, `DOMParser`, and `XMLSerializer`. This allows us to test DOM operations without a real browser. + +The `jest.setup.js` file configures the test environment and provides any necessary mocks for browser APIs that JSDOM doesn't implement. + +## Coverage Requirements + +New features should aim for at least 80% test coverage, with a focus on testing: + +1. Normal usage patterns +2. Edge cases and error handling +3. Configuration options +4. Cross-environment compatibility + +## Debugging Tests + +If you encounter issues with tests, you can use the following techniques: + +1. Run a single test file: `npx jest path/to/file.test.ts` +2. Debug a specific test: `npx jest -t "test name pattern" --runInBand` +3. Increase verbosity: `npx jest --verbose` +4. Debug in Node.js: Add `debugger` statements and run with `node --inspect-brk node_modules/.bin/jest --runInBand` \ No newline at end of file diff --git a/test/XJX.test.ts b/test/XJX.test.ts new file mode 100644 index 0000000..6eeb071 --- /dev/null +++ b/test/XJX.test.ts @@ -0,0 +1,170 @@ +/** + * XJX library tests + */ +import { XJX } from '../src/XJX'; + +describe('XJX', () => { + let xjx: XJX; + + beforeEach(() => { + // Create a fresh XJX instance before each test + xjx = new XJX(); + }); + + afterEach(() => { + // Clean up after each test + xjx.cleanup(); + }); + + describe('xmlToJson', () => { + it('should convert a simple XML string to JSON', () => { + const xml = 'Test'; + const result = xjx.xmlToJson(xml); + + expect(result).toHaveProperty('root'); + expect(result.root).toHaveProperty('$children'); + expect(result.root.$children[0]).toHaveProperty('item'); + expect(result.root.$children[0].item).toHaveProperty('$val', 'Test'); + }); + + it('should handle XML attributes correctly', () => { + const xml = 'Test'; + const result = xjx.xmlToJson(xml); + + expect(result.root.$children[0].item).toHaveProperty('$attr'); + expect(result.root.$children[0].item.$attr[0].id).toHaveProperty('$val', '123'); + }); + + it('should handle namespaces correctly when enabled', () => { + const xml = 'Test'; + const result = xjx.xmlToJson(xml); + + expect(result.root).toHaveProperty('$ns'); + expect(result.root.$children[0]).toHaveProperty('item'); + expect(result.root.$children[0].item).toHaveProperty('$ns', 'http://example.org'); + expect(result.root.$children[0].item).toHaveProperty('$pre', 'ns'); + }); + + it('should handle CDATA sections correctly', () => { + const xml = 'bold text]]>'; + const result = xjx.xmlToJson(xml); + + expect(result.root.$children[0].item.$children[0]).toHaveProperty('$cdata', 'bold text'); + }); + + it('should handle comments correctly when enabled', () => { + const xml = 'Test'; + const result = xjx.xmlToJson(xml); + + expect(result.root.$children[0]).toHaveProperty('$cmnt', ' This is a comment '); + }); + }); + + describe('jsonToXml', () => { + it('should convert a JSON object back to XML', () => { + const json = { + root: { + $children: [ + { + item: { + $val: 'Test' + } + } + ] + } + }; + + const result = xjx.jsonToXml(json); + expect(result).toContain(''); + expect(result).toContain('Test'); + expect(result).toContain(''); + }); + + it('should include XML declaration when enabled', () => { + const json = { root: { $val: 'Test' } }; + const result = xjx.jsonToXml(json); + + expect(result).toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); + }); + + it('should handle attributes correctly', () => { + const json = { + root: { + $children: [ + { + item: { + $attr: [ + { id: { $val: '123' } } + ], + $val: 'Test' + } + } + ] + } + }; + + const result = xjx.jsonToXml(json); + expect(result).toContain('Test'); + }); + }); + + describe('getPath', () => { + it('should retrieve values using dot notation', () => { + const json = { + root: { + $children: [ + { + item: { + $attr: [ + { id: { $val: '123' } } + ], + $children: [ + { name: { $val: 'Test Item' } } + ] + } + } + ] + } + }; + + expect(xjx.getPath(json, 'root.$children.0.item.$children.0.name.$val')).toBe('Test Item'); + expect(xjx.getPath(json, 'root.$children.0.item.$attr.0.id.$val')).toBe('123'); + }); + + it('should return fallback value when path does not exist', () => { + const json = { root: { $val: 'Test' } }; + + expect(xjx.getPath(json, 'root.item', 'Not Found')).toBe('Not Found'); + }); + }); + + describe('prettyPrintXml', () => { + it('should format XML with proper indentation', () => { + const xml = 'Test123'; + const result = xjx.prettyPrintXml(xml); + + // Check for line breaks and indentation + expect(result).toContain('\n'); + expect(result).toContain(' '); + expect(result).toContain(' '); + }); + }); + + describe('validateXML', () => { + it('should return true for valid XML', () => { + const xml = 'Test'; + const result = xjx.validateXML(xml); + + expect(result.isValid).toBe(true); + expect(result.message).toBeUndefined(); + }); + + it('should return false with error message for invalid XML', () => { + const xml = 'Test { + afterEach(() => { + // Clean up after each test to prevent memory leaks + DOMAdapter.cleanup(); + }); + + describe('DOM methods', () => { + it('should create a DOM parser', () => { + const parser = DOMAdapter.createParser(); + expect(parser).toBeDefined(); + expect(typeof parser.parseFromString).toBe('function'); + }); + + it('should create an XML serializer', () => { + const serializer = DOMAdapter.createSerializer(); + expect(serializer).toBeDefined(); + expect(typeof serializer.serializeToString).toBe('function'); + }); + + it('should parse XML strings', () => { + const xml = 'Test'; + const doc = DOMAdapter.parseFromString(xml); + + expect(doc.documentElement.nodeName).toBe('root'); + expect(doc.documentElement.childNodes.length).toBeGreaterThan(0); + }); + + it('should serialize DOM nodes to XML strings', () => { + const xml = 'Test'; + const doc = DOMAdapter.parseFromString(xml); + const serialized = DOMAdapter.serializeToString(doc); + + // JSDOM serialization may add XML declaration and namespace + expect(serialized).toContain(''); + expect(serialized).toContain(''); + expect(serialized).toContain('Test'); + }); + + it('should create new documents', () => { + const doc = DOMAdapter.createDocument(); + expect(doc.nodeType).toBe(document.DOCUMENT_NODE); + }); + + it('should create elements', () => { + const element = DOMAdapter.createElement('test'); + expect(element.nodeName).toBe('TEST'); + expect(element.nodeType).toBe(DOMAdapter.nodeTypes.ELEMENT_NODE); + }); + + it('should create elements with namespaces', () => { + const nsURI = 'http://example.org'; + const element = DOMAdapter.createElementNS(nsURI, 'ns:test'); + + expect(element.nodeName).toBe('ns:test'); + expect(element.namespaceURI).toBe(nsURI); + }); + + it('should create text nodes', () => { + const text = DOMAdapter.createTextNode('Test content'); + + expect(text.nodeType).toBe(DOMAdapter.nodeTypes.TEXT_NODE); + expect(text.nodeValue).toBe('Test content'); + }); + + it('should create CDATA sections', () => { + const cdata = DOMAdapter.createCDATASection('bold'); + + expect(cdata.nodeType).toBe(DOMAdapter.nodeTypes.CDATA_SECTION_NODE); + expect(cdata.nodeValue).toBe('bold'); + }); + + it('should create comments', () => { + const comment = DOMAdapter.createComment('Test comment'); + + expect(comment.nodeType).toBe(DOMAdapter.nodeTypes.COMMENT_NODE); + expect(comment.nodeValue).toBe('Test comment'); + }); + + it('should create processing instructions', () => { + const pi = DOMAdapter.createProcessingInstruction('xml-stylesheet', 'href="style.css"'); + + expect(pi.nodeType).toBe(DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE); + expect(pi.target).toBe('xml-stylesheet'); + expect(pi.data).toBe('href="style.css"'); + }); + }); + + describe('Helper methods', () => { + it('should set namespaced attributes', () => { + const element = DOMAdapter.createElement('test'); + DOMAdapter.setNamespacedAttribute( + element, + 'http://example.org', + 'ns:attr', + 'value' + ); + + expect(element.getAttributeNS('http://example.org', 'attr')).toBe('value'); + }); + + it('should set regular attributes when namespace is null', () => { + const element = DOMAdapter.createElement('test'); + DOMAdapter.setNamespacedAttribute( + element, + null, + 'attr', + 'value' + ); + + expect(element.getAttribute('attr')).toBe('value'); + }); + + it('should detect DOM nodes', () => { + const element = DOMAdapter.createElement('test'); + const text = DOMAdapter.createTextNode('Test'); + + expect(DOMAdapter.isNode(element)).toBe(true); + expect(DOMAdapter.isNode(text)).toBe(true); + expect(DOMAdapter.isNode({})).toBe(false); + expect(DOMAdapter.isNode('not a node')).toBe(false); + }); + + it('should get node type names', () => { + expect(DOMAdapter.getNodeTypeName(DOMAdapter.nodeTypes.ELEMENT_NODE)) + .toBe('ELEMENT_NODE'); + expect(DOMAdapter.getNodeTypeName(DOMAdapter.nodeTypes.TEXT_NODE)) + .toBe('TEXT_NODE'); + expect(DOMAdapter.getNodeTypeName(DOMAdapter.nodeTypes.COMMENT_NODE)) + .toBe('COMMENT_NODE'); + expect(DOMAdapter.getNodeTypeName(999)) + .toBe('UNKNOWN_NODE_TYPE(999)'); + }); + + it('should get all node attributes as an object', () => { + const element = DOMAdapter.createElement('test'); + element.setAttribute('id', '123'); + element.setAttribute('class', 'test-class'); + + const attrs = DOMAdapter.getNodeAttributes(element); + + expect(attrs).toEqual({ + id: '123', + class: 'test-class' + }); + }); + }); + + describe('Error handling', () => { + it('should handle errors when parsing invalid XML', () => { + try { + // JSDOM's parser is quite forgiving, so we need to mock a parsing error + jest.spyOn(DOMAdapter, 'parseFromString').mockImplementationOnce(() => { + throw new Error('Mocked parsing error'); + }); + + DOMAdapter.parseFromString(''); + fail('Should have thrown an error'); + } catch (error) { + expect(error).toBeInstanceOf(XMLToJSONError); + expect((error as Error).message).toContain('Failed to parse XML'); + } + }); + }); +}); \ No newline at end of file diff --git a/test/core/utils/JSONUtil.test.js b/test/core/utils/JSONUtil.test.js new file mode 100644 index 0000000..ca31596 --- /dev/null +++ b/test/core/utils/JSONUtil.test.js @@ -0,0 +1,235 @@ +/** + * Tests for JSONUtil class + */ +import { JSONUtil } from '../../../src/core/JSONUtil'; + +describe('JSONUtil', () => { + describe('getPath', () => { + it('should retrieve values using dot notation', () => { + const json = { + user: { + name: "John", + contact: { + email: "john@example.com" + } + } + }; + + expect(JSONUtil.getPath(json, 'user.name')).toBe('John'); + expect(JSONUtil.getPath(json, 'user.contact.email')).toBe('john@example.com'); + }); + + it('should traverse arrays automatically', () => { + const json = { + users: [ + { id: 1, name: "John" }, + { id: 2, name: "Jane" } + ] + }; + + const names = JSONUtil.getPath(json, 'users.name'); + expect(Array.isArray(names)).toBe(true); + expect(names).toEqual(['John', 'Jane']); + }); + + it('should return fallback value when path does not exist', () => { + const json = { user: { name: "John" } }; + + expect(JSONUtil.getPath(json, 'user.age', 30)).toBe(30); + expect(JSONUtil.getPath(json, 'company.name', 'Unknown')).toBe('Unknown'); + }); + + it('should handle XML-like JSON structures', () => { + const json = { + root: { + $children: [ + { item: { $val: "Item 1" } }, + { item: { $val: "Item 2" } } + ] + } + }; + + expect(JSONUtil.getPath(json, 'root.$children.item.$val')).toEqual(["Item 1", "Item 2"]); + }); + + it('should collapse singleton arrays', () => { + const json = { + user: { + roles: ["admin"] + } + }; + + expect(JSONUtil.getPath(json, 'user.roles')).toBe('admin'); + }); + }); + + describe('fromJSONObject', () => { + it('should convert a plain JSON object to XML-like JSON structure', () => { + const json = { + name: "John", + age: 30 + }; + + const result = JSONUtil.fromJSONObject(json); + + expect(result).toHaveProperty('$children'); + expect(result.$children).toHaveLength(2); + expect(result.$children[0].name).toHaveProperty('$val', 'John'); + expect(result.$children[1].age).toHaveProperty('$val', 30); + }); + + it('should wrap result in a root element if provided', () => { + const json = { name: "John" }; + const result = JSONUtil.fromJSONObject(json, "user"); + + expect(result).toHaveProperty('user'); + expect(result.user).toHaveProperty('$children'); + }); + + it('should handle arrays correctly', () => { + const json = { + items: ["A", "B", "C"] + }; + + const result = JSONUtil.fromJSONObject(json); + expect(result.$children[0].items).toHaveProperty('$children'); + expect(result.$children[0].items.$children).toHaveLength(3); + expect(result.$children[0].items.$children[0]).toHaveProperty('$val', 'A'); + }); + + it('should handle complex root configuration', () => { + const json = { name: "John" }; + const result = JSONUtil.fromJSONObject(json, { + name: "user", + $pre: "ns", + $ns: "http://example.org", + $attrs: [ + { id: { $val: "u1" } } + ] + }); + + expect(result).toHaveProperty('ns:user'); + expect(result['ns:user']).toHaveProperty('$ns', 'http://example.org'); + expect(result['ns:user']).toHaveProperty('$attrs'); + expect(result['ns:user'].$attrs[0].id).toHaveProperty('$val', 'u1'); + }); + }); + + describe('isEmpty', () => { + it('should return true for null and undefined', () => { + expect(JSONUtil.isEmpty(null)).toBe(true); + expect(JSONUtil.isEmpty(undefined)).toBe(true); + }); + + it('should return true for empty arrays', () => { + expect(JSONUtil.isEmpty([])).toBe(true); + }); + + it('should return true for empty objects', () => { + expect(JSONUtil.isEmpty({})).toBe(true); + }); + + it('should return false for non-empty arrays', () => { + expect(JSONUtil.isEmpty([1, 2, 3])).toBe(false); + }); + + it('should return false for non-empty objects', () => { + expect(JSONUtil.isEmpty({ key: 'value' })).toBe(false); + }); + + it('should return false for primitive values', () => { + expect(JSONUtil.isEmpty(0)).toBe(false); + expect(JSONUtil.isEmpty('')).toBe(false); + expect(JSONUtil.isEmpty(false)).toBe(false); + }); + }); + + describe('safeStringify', () => { + it('should stringify valid JSON objects', () => { + const obj = { name: "John", age: 30 }; + const result = JSONUtil.safeStringify(obj); + + expect(result).toBe(JSON.stringify(obj, null, 2)); + }); + + it('should handle circular references gracefully', () => { + const obj: any = { name: "John" }; + obj.self = obj; // Create circular reference + + const result = JSONUtil.safeStringify(obj); + expect(result).toBe('[Cannot stringify object]'); + }); + + it('should respect custom indent', () => { + const obj = { name: "John", age: 30 }; + const result = JSONUtil.safeStringify(obj, 4); + + expect(result).toBe(JSON.stringify(obj, null, 4)); + }); + }); + + describe('deepClone and deepMerge', () => { + it('should create a deep clone of an object', () => { + const original = { + name: "John", + contact: { + email: "john@example.com" + }, + tags: ["user", "admin"] + }; + + const clone = JSONUtil.deepClone(original); + + expect(clone).toEqual(original); + expect(clone).not.toBe(original); + expect(clone.contact).not.toBe(original.contact); + expect(clone.tags).not.toBe(original.tags); + }); + + it('should deep merge two objects', () => { + const target = { + name: "John", + contact: { + email: "john@example.com" + }, + settings: { + theme: "dark" + } + }; + + const source = { + age: 30, + contact: { + phone: "555-1234" + }, + settings: { + notifications: true + } + }; + + const result = JSONUtil.deepMerge(target, source); + + expect(result).toBe(target); // Should modify target + expect(result.name).toBe("John"); + expect(result.age).toBe(30); + expect(result.contact.email).toBe("john@example.com"); + expect(result.contact.phone).toBe("555-1234"); + expect(result.settings.theme).toBe("dark"); + expect(result.settings.notifications).toBe(true); + }); + + it('should handle arrays during merge', () => { + const target = { tags: ["user"] }; + const source = { tags: ["admin"] }; + + const result = JSONUtil.deepMerge(target, source); + + expect(result.tags).toEqual(["admin"]); + }); + + it('should handle null and undefined values', () => { + expect(JSONUtil.deepMerge({ name: "John" }, null)).toEqual({ name: "John" }); + expect(JSONUtil.deepMerge(null, { name: "John" })).toEqual({ name: "John" }); + }); + }); +}); \ No newline at end of file diff --git a/test/core/utils/XMLUtil.test.js b/test/core/utils/XMLUtil.test.js new file mode 100644 index 0000000..7200e48 --- /dev/null +++ b/test/core/utils/XMLUtil.test.js @@ -0,0 +1,159 @@ +/** + * Tests for XMLUtil class + */ +import { XMLUtil } from '../../../src/core/XMLUtil'; +import { DOMAdapter } from '../../../src/core/DOMAdapter'; + +describe('XMLUtil', () => { + describe('prettyPrintXml', () => { + it('should format XML with proper indentation', () => { + const xml = 'Test123'; + const result = XMLUtil.prettyPrintXml(xml); + + expect(result).toContain('\n'); + expect(result).toContain(' '); + expect(result).toContain(' '); + }); + + it('should handle XML with attributes', () => { + const xml = 'Test'; + const result = XMLUtil.prettyPrintXml(xml); + + expect(result).toContain(''); + }); + + it('should handle empty elements correctly', () => { + const xml = ''; + const result = XMLUtil.prettyPrintXml(xml); + + expect(result).toContain(''); + expect(result).toContain(''); + expect(result).toContain(''); + }); + + it('should respect custom indentation', () => { + const xml = 'Test'; + const result = XMLUtil.prettyPrintXml(xml, 4); + + expect(result).toContain('\n'); + expect(result).toContain(' '); + expect(result).toContain(' '); + }); + }); + + describe('validateXML', () => { + it('should return true for valid XML', () => { + const xml = 'Test'; + const result = XMLUtil.validateXML(xml); + + expect(result.isValid).toBe(true); + expect(result.message).toBeUndefined(); + }); + + it('should return false for XML with unclosed tags', () => { + const xml = 'Test'; + const result = XMLUtil.validateXML(xml); + + expect(result.isValid).toBe(false); + expect(result.message).toBeDefined(); + }); + + it('should return false for XML with malformed attributes', () => { + const xml = 'Test'; + const result = XMLUtil.validateXML(xml); + + expect(result.isValid).toBe(false); + expect(result.message).toBeDefined(); + }); + + it('should return false for non-XML content', () => { + const xml = 'This is not XML'; + const result = XMLUtil.validateXML(xml); + + expect(result.isValid).toBe(false); + expect(result.message).toBeDefined(); + }); + }); + + describe('ensureXMLDeclaration', () => { + it('should add XML declaration if missing', () => { + const xml = 'Test'; + const result = XMLUtil.ensureXMLDeclaration(xml); + + expect(result).toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); + expect(result).toContain(''); + }); + + it('should not add XML declaration if already present', () => { + const xml = 'Test'; + const result = XMLUtil.ensureXMLDeclaration(xml); + + expect(result).toBe(xml); + }); + + it('should handle XML declaration with different attributes', () => { + const xml = 'Test'; + const result = XMLUtil.ensureXMLDeclaration(xml); + + expect(result).toBe(xml); + }); + }); + + describe('escapeXML & unescapeXML', () => { + it('should escape special XML characters', () => { + const input = 'Text & More'; + const result = XMLUtil.escapeXML(input); + + expect(result).toBe('<tag attr="value">Text & More</tag>'); + }); + + it('should unescape XML entities', () => { + const input = '<tag attr="value">Text & More</tag>'; + const result = XMLUtil.unescapeXML(input); + + expect(result).toBe('Text & More'); + }); + + it('should handle round-trip escape/unescape correctly', () => { + const input = 'John & Jane'; + const escaped = XMLUtil.escapeXML(input); + const unescaped = XMLUtil.unescapeXML(escaped); + + expect(unescaped).toBe(input); + }); + }); + + describe('extractPrefix & extractLocalName', () => { + it('should extract namespace prefix from qualified name', () => { + expect(XMLUtil.extractPrefix('ns:element')).toBe('ns'); + expect(XMLUtil.extractPrefix('prefix:tag')).toBe('prefix'); + }); + + it('should return null for names without prefix', () => { + expect(XMLUtil.extractPrefix('element')).toBeNull(); + expect(XMLUtil.extractPrefix('tag')).toBeNull(); + }); + + it('should extract local name from qualified name', () => { + expect(XMLUtil.extractLocalName('ns:element')).toBe('element'); + expect(XMLUtil.extractLocalName('prefix:tag')).toBe('tag'); + }); + + it('should return the name itself for names without prefix', () => { + expect(XMLUtil.extractLocalName('element')).toBe('element'); + expect(XMLUtil.extractLocalName('tag')).toBe('tag'); + }); + }); + + describe('createQualifiedName', () => { + it('should create qualified name with prefix', () => { + expect(XMLUtil.createQualifiedName('ns', 'element')).toBe('ns:element'); + expect(XMLUtil.createQualifiedName('prefix', 'tag')).toBe('prefix:tag'); + }); + + it('should return only local name when prefix is null', () => { + expect(XMLUtil.createQualifiedName(null, 'element')).toBe('element'); + expect(XMLUtil.createQualifiedName(null, 'tag')).toBe('tag'); + }); + }); +}); \ No newline at end of file diff --git a/test/jest.setup.js b/test/jest.setup.js new file mode 100644 index 0000000..31459fc --- /dev/null +++ b/test/jest.setup.js @@ -0,0 +1,40 @@ +// Jest setup file for the XJX library tests + +// JSDOM environment should already be set up by Jest's testEnvironment configuration, +// but we can add any additional mocks or configuration here if needed. + +// In case we need to mock any browser features that JSDOM doesn't provide +if (typeof window !== 'undefined') { + // If XMLSerializer isn't available in the JSDOM environment, mock it + if (!window.XMLSerializer) { + window.XMLSerializer = class XMLSerializer { + serializeToString(node) { + return `${node.nodeName}`; + } + }; + } + + // If DOMParser isn't available in the JSDOM environment, mock it + if (!window.DOMParser) { + window.DOMParser = class DOMParser { + parseFromString(xmlString, mimeType) { + const document = window.document.implementation.createDocument(null, 'root', null); + + // Create a basic document structure for testing + const mockElement = document.createElement('mockElement'); + mockElement.textContent = xmlString; + document.documentElement.appendChild(mockElement); + + return document; + } + }; + } + } + + // Silence console errors during tests to keep output clean + jest.spyOn(console, 'error').mockImplementation(() => {}); + + // Reset all mocks after each test + afterEach(() => { + jest.clearAllMocks(); + }); \ No newline at end of file From 08c5fa1567fb312e5399dfceff65062a0bc56f14 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 17:22:18 -0500 Subject: [PATCH 13/38] fixed missing document node definition --- src/core/DOMAdapter.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/DOMAdapter.ts b/src/core/DOMAdapter.ts index d3d98a1..fe1b798 100644 --- a/src/core/DOMAdapter.ts +++ b/src/core/DOMAdapter.ts @@ -9,6 +9,7 @@ interface NodeTypes { CDATA_SECTION_NODE: number; COMMENT_NODE: number; PROCESSING_INSTRUCTION_NODE: number; + DOCUMENT_NODE: number; } interface DOMWindow { @@ -20,9 +21,10 @@ interface DOMWindow { CDATA_SECTION_NODE: number; COMMENT_NODE: number; PROCESSING_INSTRUCTION_NODE: number; + DOCUMENT_NODE: number; }; document: Document; - close?: () => void; // Added close method as optional + close?: () => void; } interface JSDOMInstance { @@ -54,6 +56,7 @@ export const DOMAdapter = (() => { CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE, COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE, PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE, + DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line }; docImplementation = jsdomInstance.window.document.implementation; } catch (jsdomError) { @@ -69,6 +72,7 @@ export const DOMAdapter = (() => { CDATA_SECTION_NODE: 4, COMMENT_NODE: 8, PROCESSING_INSTRUCTION_NODE: 7, + DOCUMENT_NODE: 9, }; const implementation = new DOMImplementation(); docImplementation = implementation; @@ -94,6 +98,7 @@ export const DOMAdapter = (() => { CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE, COMMENT_NODE: Node.COMMENT_NODE, PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE, + DOCUMENT_NODE: Node.DOCUMENT_NODE, }; docImplementation = document.implementation; } From 56503c1b7b7d40d94e4f7bbb3aaac1323892d5cf Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 17:30:52 -0500 Subject: [PATCH 14/38] improved xml entity escaping --- src/core/utils/XMLUtil.ts | 100 ++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/src/core/utils/XMLUtil.ts b/src/core/utils/XMLUtil.ts index 77e898b..66f5bb8 100644 --- a/src/core/utils/XMLUtil.ts +++ b/src/core/utils/XMLUtil.ts @@ -15,7 +15,7 @@ export class XMLUtil { const INDENT = " ".repeat(indent); try { - const doc = DOMAdapter.parseFromString(xmlString, 'text/xml'); + const doc = DOMAdapter.parseFromString(xmlString, "text/xml"); const serializer = (node: Node, level = 0): string => { const pad = INDENT.repeat(level); @@ -76,7 +76,11 @@ export class XMLUtil { return serializer(doc).trim(); } catch (error) { - throw new XMLToJSONError(`Failed to pretty print XML: ${error instanceof Error ? error.message : String(error)}`); + throw new XMLToJSONError( + `Failed to pretty print XML: ${ + error instanceof Error ? error.message : String(error) + }` + ); } } @@ -85,18 +89,24 @@ export class XMLUtil { * @param xmlString XML string to validate * @returns Object with validation result and any error messages */ - static validateXML(xmlString: string): { isValid: boolean; message?: string } { + static validateXML(xmlString: string): { + isValid: boolean; + message?: string; + } { try { const doc = DOMAdapter.parseFromString(xmlString, "text/xml"); const errors = doc.getElementsByTagName("parsererror"); if (errors.length > 0) { - return { isValid: false, message: errors[0].textContent || "Unknown parsing error" }; + return { + isValid: false, + message: errors[0].textContent || "Unknown parsing error", + }; } return { isValid: true }; } catch (error) { - return { - isValid: false, - message: error instanceof Error ? error.message : String(error) + return { + isValid: false, + message: error instanceof Error ? error.message : String(error), }; } } @@ -107,38 +117,66 @@ export class XMLUtil { * @returns XML string with declaration */ static ensureXMLDeclaration(xmlString: string): string { - if (!xmlString.trim().startsWith('\n' + xmlString; } return xmlString; } /** - * Escape special XML characters - * @param text Text to escape - * @returns Escaped text + * Escapes special characters in text for safe XML usage. + * @param text Text to escape. + * @returns Escaped XML string. */ static escapeXML(text: string): string { - return text - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); + if (typeof text !== "string" || text.length === 0) { + return ""; + } + + return text.replace(/[&<>"']/g, (char) => { + switch (char) { + case "&": + return "&"; + case "<": + return "<"; + case ">": + return ">"; + case '"': + return """; + case "'": + return "'"; + default: + return char; + } + }); } /** - * Unescape XML entities - * @param text Text with XML entities - * @returns Unescaped text + * Unescapes XML entities back to their character equivalents. + * @param text Text with XML entities. + * @returns Unescaped text. */ static unescapeXML(text: string): string { - return text - .replace(/&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/"/g, '"') - .replace(/'/g, "'"); + if (typeof text !== "string" || text.length === 0) { + return ""; + } + + return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => { + switch (entity) { + case "amp": + return "&"; + case "lt": + return "<"; + case "gt": + return ">"; + case "quot": + return '"'; + case "apos": + return "'"; + default: + return match; + } + }); } /** @@ -147,7 +185,7 @@ export class XMLUtil { * @returns Prefix or null if no prefix */ static extractPrefix(qualifiedName: string): string | null { - const colonIndex = qualifiedName.indexOf(':'); + const colonIndex = qualifiedName.indexOf(":"); return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null; } @@ -157,8 +195,10 @@ export class XMLUtil { * @returns Local name */ static extractLocalName(qualifiedName: string): string { - const colonIndex = qualifiedName.indexOf(':'); - return colonIndex > 0 ? qualifiedName.substring(colonIndex + 1) : qualifiedName; + const colonIndex = qualifiedName.indexOf(":"); + return colonIndex > 0 + ? qualifiedName.substring(colonIndex + 1) + : qualifiedName; } /** @@ -170,4 +210,4 @@ export class XMLUtil { static createQualifiedName(prefix: string | null, localName: string): string { return prefix ? `${prefix}:${localName}` : localName; } -} \ No newline at end of file +} From 078e8a671de2f133093d22c523b90f65fe64ae2d Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 18:46:53 -0500 Subject: [PATCH 15/38] consistent configuration passing --- src/XJX.ts | 30 +++++++----- src/core/JSONToXML.ts | 74 ++++++++++++++++++----------- src/core/XMLToJSON.ts | 32 ++++++++----- src/core/config/config.ts | 4 +- src/core/types/types.ts | 4 +- src/core/utils/JSONUtil.ts | 96 ++++++++++++++++++++++++++------------ src/core/utils/XMLUtil.ts | 31 ++++++++---- src/index.ts | 4 +- 8 files changed, 178 insertions(+), 97 deletions(-) diff --git a/src/XJX.ts b/src/XJX.ts index ac7b893..96fb111 100644 --- a/src/XJX.ts +++ b/src/XJX.ts @@ -3,25 +3,31 @@ */ import { XMLToJSON } from "./core/XMLToJSON"; import { JSONToXML } from "./core/JSONToXML"; -import { XMLToJSONConfig } from "./core/types/types"; +import { Configuration } from "./core/types/types"; import { DEFAULT_CONFIG } from "./core/config/config"; import { DOMAdapter } from "./core/DOMAdapter"; import { XMLUtil } from "./core/utils/XMLUtil"; import { JSONUtil } from "./core/utils/JSONUtil"; export class XJX { - private parser: XMLToJSON; - private serializer: JSONToXML; - private config: XMLToJSONConfig; + private config: Configuration; + private xmltojson: XMLToJSON; + private jsontoxml: JSONToXML; + private jsonUtil: JSONUtil; + private xmlUtil: XMLUtil; /** * Constructor for XJX utility * @param config Configuration options */ - constructor(config: Partial = {}) { + constructor(config: Partial = {}) { this.config = { ...DEFAULT_CONFIG, ...config }; - this.parser = new XMLToJSON(this.config); - this.serializer = new JSONToXML(this.config); + + // Initialize all components with config + this.jsonUtil = new JSONUtil(this.config); + this.xmlUtil = new XMLUtil(this.config); + this.xmltojson = new XMLToJSON(this.config); + this.jsontoxml = new JSONToXML(this.config); } /** @@ -30,7 +36,7 @@ export class XJX { * @returns JSON object representing the XML content */ public xmlToJson(xmlString: string): Record { - return this.parser.parse(xmlString); + return this.xmltojson.parse(xmlString); } /** @@ -39,7 +45,7 @@ export class XJX { * @returns XML string */ public jsonToXml(jsonObj: Record): string { - return this.serializer.serialize(jsonObj); + return this.jsontoxml.serialize(jsonObj); } /** @@ -48,7 +54,7 @@ export class XJX { * @returns Formatted XML string */ public prettyPrintXml(xmlString: string): string { - return XMLUtil.prettyPrintXml(xmlString, this.config.outputOptions.indent); + return this.xmlUtil.prettyPrintXml(xmlString); } /** @@ -63,7 +69,7 @@ export class XJX { path: string, fallback: any = undefined ): any { - return JSONUtil.getPath(obj, path, fallback); + return this.jsonUtil.getPath(obj, path, fallback); } /** @@ -72,7 +78,7 @@ export class XJX { * @returns Validation result */ public validateXML(xmlString: string): { isValid: boolean; message?: string } { - return XMLUtil.validateXML(xmlString); + return this.xmlUtil.validateXML(xmlString); } /** diff --git a/src/core/JSONToXML.ts b/src/core/JSONToXML.ts index b53fa64..86b5fa3 100644 --- a/src/core/JSONToXML.ts +++ b/src/core/JSONToXML.ts @@ -1,7 +1,7 @@ /** * JSONToXML class for converting JSON to XML with consistent namespace handling */ -import { XMLToJSONConfig } from "./types/types"; +import { Configuration } from "./types/types"; import { XMLToJSONError } from "./types/errors"; import { DOMAdapter } from "./DOMAdapter"; import { XMLUtil } from "./utils/XMLUtil"; @@ -10,14 +10,16 @@ import { XMLUtil } from "./utils/XMLUtil"; * JSONToXML for converting JSON to XML */ export class JSONToXML { - private config: XMLToJSONConfig; + private config: Configuration; + private xmlUtil: XMLUtil; /** * Constructor for JSONToXML * @param config Configuration options */ - constructor(config: XMLToJSONConfig) { + constructor(config: Configuration) { this.config = config; + this.xmlUtil = new XMLUtil(this.config); } /** @@ -42,12 +44,12 @@ export class JSONToXML { // Add XML declaration if specified let xmlString = DOMAdapter.serializeToString(doc); if (this.config.outputOptions.xml.declaration) { - xmlString = XMLUtil.ensureXMLDeclaration(xmlString); + xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString); } // Apply pretty printing if enabled if (this.config.outputOptions.prettyPrint) { - xmlString = XMLUtil.prettyPrintXml(xmlString, this.config.outputOptions.indent); + xmlString = this.xmlUtil.prettyPrintXml(xmlString); } return xmlString; @@ -60,6 +62,12 @@ export class JSONToXML { } } + /** + * Convert JSON object to DOM node + * @param jsonObj JSON object to convert + * @param doc Document for creating elements + * @returns DOM Element + */ /** * Convert JSON object to DOM node * @param jsonObj JSON object to convert @@ -84,8 +92,10 @@ export class JSONToXML { // Create element with namespace if available let element: Element; - const ns = nodeData[this.config.propNames.namespace]; - const prefix = nodeData[this.config.propNames.prefix]; + const namespaceKey = this.config.propNames.namespace; + const prefixKey = this.config.propNames.prefix; + const ns = nodeData[namespaceKey]; + const prefix = nodeData[prefixKey]; if (ns && this.config.preserveNamespaces) { if (prefix) { @@ -101,20 +111,22 @@ export class JSONToXML { } // Process attributes if enabled + const attributesKey = this.config.propNames.attributes; + const valueKey = this.config.propNames.value; if ( this.config.preserveAttributes && - nodeData[this.config.propNames.attributes] && - Array.isArray(nodeData[this.config.propNames.attributes]) + nodeData[attributesKey] && + Array.isArray(nodeData[attributesKey]) ) { - nodeData[this.config.propNames.attributes].forEach( + nodeData[attributesKey].forEach( (attrObj: Record) => { const attrName = Object.keys(attrObj)[0]; if (!attrName) return; const attrData = attrObj[attrName]; - const attrValue = attrData[this.config.propNames.value] || ""; - const attrNs = attrData[this.config.propNames.namespace]; - const attrPrefix = attrData[this.config.propNames.prefix]; + const attrValue = attrData[valueKey] || ""; + const attrNs = attrData[namespaceKey]; + const attrPrefix = attrData[prefixKey]; // Form qualified name for attribute if it has a prefix let qualifiedName = attrName; @@ -133,56 +145,62 @@ export class JSONToXML { } // Process simple text value - if (nodeData[this.config.propNames.value] !== undefined) { - element.textContent = nodeData[this.config.propNames.value]; + if (nodeData[valueKey] !== undefined) { + element.textContent = nodeData[valueKey]; } // Process children + const childrenKey = this.config.propNames.children; + const cdataKey = this.config.propNames.cdata; + const commentsKey = this.config.propNames.comments; + const instructionKey = this.config.propNames.instruction; + const targetKey = this.config.propNames.target; + if ( - nodeData[this.config.propNames.children] && - Array.isArray(nodeData[this.config.propNames.children]) + nodeData[childrenKey] && + Array.isArray(nodeData[childrenKey]) ) { - nodeData[this.config.propNames.children].forEach( + nodeData[childrenKey].forEach( (child: Record) => { // Text nodes if ( - child[this.config.propNames.value] !== undefined && + child[valueKey] !== undefined && this.config.preserveTextNodes ) { element.appendChild( - DOMAdapter.createTextNode(child[this.config.propNames.value]) + DOMAdapter.createTextNode(child[valueKey]) ); } // CDATA sections else if ( - child[this.config.propNames.cdata] !== undefined && + child[cdataKey] !== undefined && this.config.preserveCDATA ) { element.appendChild( DOMAdapter.createCDATASection( - child[this.config.propNames.cdata] + child[cdataKey] ) ); } // Comments else if ( - child[this.config.propNames.comments] !== undefined && + child[commentsKey] !== undefined && this.config.preserveComments ) { element.appendChild( DOMAdapter.createComment( - child[this.config.propNames.comments] + child[commentsKey] ) ); } // Processing instructions else if ( - child[this.config.propNames.instruction] !== undefined && + child[instructionKey] !== undefined && this.config.preserveProcessingInstr ) { - const piData = child[this.config.propNames.instruction]; - const target = piData[this.config.propNames.target]; - const data = piData[this.config.propNames.value] || ""; + const piData = child[instructionKey]; + const target = piData[targetKey]; + const data = piData[valueKey] || ""; if (target) { element.appendChild( diff --git a/src/core/XMLToJSON.ts b/src/core/XMLToJSON.ts index 6144c6f..ca90271 100644 --- a/src/core/XMLToJSON.ts +++ b/src/core/XMLToJSON.ts @@ -1,7 +1,7 @@ /** * XMLToJSON class for converting XML to JSON with consistent namespace handling */ -import { XMLToJSONConfig } from "./types/types"; +import { Configuration } from "./types/types"; import { XMLToJSONError } from "./types/errors"; import { DOMAdapter } from "./DOMAdapter"; import { JSONUtil } from "./utils/JSONUtil"; @@ -10,14 +10,16 @@ import { JSONUtil } from "./utils/JSONUtil"; * XMLToJSON Parser for converting XML to JSON */ export class XMLToJSON { - private config: XMLToJSONConfig; + private config: Configuration; + private jsonUtil: JSONUtil; /** * Constructor for XMLToJSON * @param config Configuration options */ - constructor(config: XMLToJSONConfig) { + constructor(config: Configuration) { this.config = config; + this.jsonUtil = new JSONUtil(this.config); } /** @@ -120,6 +122,12 @@ export class XMLToJSON { // Process child nodes if (element.childNodes.length > 0) { const children: Array> = []; + const childrenKey = this.config.propNames.children; + const valueKey = this.config.propNames.value; + const cdataKey = this.config.propNames.cdata; + const commentsKey = this.config.propNames.comments; + const instructionKey = this.config.propNames.instruction; + const targetKey = this.config.propNames.target; for (let i = 0; i < element.childNodes.length; i++) { const child = element.childNodes[i]; @@ -134,7 +142,7 @@ export class XMLToJSON { continue; } - children.push({ [this.config.propNames.value]: text }); + children.push({ [valueKey]: text }); } } // CDATA sections @@ -143,7 +151,7 @@ export class XMLToJSON { this.config.preserveCDATA ) { children.push({ - [this.config.propNames.cdata]: child.nodeValue || "", + [cdataKey]: child.nodeValue || "", }); } // Comments @@ -152,7 +160,7 @@ export class XMLToJSON { this.config.preserveComments ) { children.push({ - [this.config.propNames.comments]: child.nodeValue || "", + [commentsKey]: child.nodeValue || "", }); } // Processing instructions @@ -162,9 +170,9 @@ export class XMLToJSON { this.config.preserveProcessingInstr ) { children.push({ - [this.config.propNames.instruction]: { - [this.config.propNames.target]: child.nodeName, - [this.config.propNames.value]: child.nodeValue || "", + [instructionKey]: { + [targetKey]: child.nodeName, + [valueKey]: child.nodeValue || "", }, }); } @@ -175,7 +183,7 @@ export class XMLToJSON { } if (children.length > 0) { - nodeObj[this.config.propNames.children] = children; + nodeObj[childrenKey] = children; } } @@ -233,8 +241,8 @@ export class XMLToJSON { const keys = Object.keys(node); if ( keys.every((key) => key === childrenKey || key === attrsKey) && - (node[childrenKey] === undefined || JSONUtil.isEmpty(node[childrenKey])) && - (node[attrsKey] === undefined || JSONUtil.isEmpty(node[attrsKey])) + (node[childrenKey] === undefined || this.jsonUtil.isEmpty(node[childrenKey])) && + (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey])) ) { return undefined; } diff --git a/src/core/config/config.ts b/src/core/config/config.ts index 2d0e458..12b056a 100644 --- a/src/core/config/config.ts +++ b/src/core/config/config.ts @@ -1,12 +1,12 @@ /** * Default configuration for the XJX library */ -import { XMLToJSONConfig } from '../types/types'; +import { Configuration } from '../types/types'; /** * Default configuration */ -export const DEFAULT_CONFIG: XMLToJSONConfig = { +export const DEFAULT_CONFIG: Configuration = { preserveNamespaces: true, preserveComments: true, preserveProcessingInstr: true, diff --git a/src/core/types/types.ts b/src/core/types/types.ts index 89867ad..4caed20 100644 --- a/src/core/types/types.ts +++ b/src/core/types/types.ts @@ -5,7 +5,7 @@ /** * Configuration interface for the library */ -export interface XMLToJSONConfig { +export interface Configuration { // Features to preserve during transformation preserveNamespaces: boolean; preserveComments: boolean; @@ -40,4 +40,4 @@ export interface XMLToJSONConfig { }; } -export default XMLToJSONConfig; \ No newline at end of file +export default Configuration; \ No newline at end of file diff --git a/src/core/utils/JSONUtil.ts b/src/core/utils/JSONUtil.ts index 7952d17..95b5ded 100644 --- a/src/core/utils/JSONUtil.ts +++ b/src/core/utils/JSONUtil.ts @@ -1,17 +1,29 @@ /** * JSONUtil - Utility functions for JSON processing */ +import { Configuration } from "../types/types"; + export class JSONUtil { + private config: Configuration; + + /** + * Constructor for JSONUtil + * @param config Configuration options + */ + constructor(config: Configuration) { + this.config = config; + } + /** * Safely retrieves a value from a JSON object using a dot-separated path. - * Automatically traverses into $children arrays and flattens results. + * Automatically traverses into children arrays and flattens results. * * @param obj The input JSON object * @param path The dot-separated path string (e.g., "root.item.description.$val") * @param fallback Value to return if the path does not resolve * @returns Retrieved value or fallback */ - static getPath( + getPath( obj: Record, path: string, fallback: any = undefined @@ -44,21 +56,41 @@ export class JSONUtil { /** * Resolves a single path segment in the context of a JSON object. - * Falls back to searching $children for matching keys. + * Falls back to searching children for matching keys. * * @param obj The current object * @param segment The path segment to resolve * @returns Resolved value or undefined */ - private static resolveSegment(obj: any, segment: string): any { + private resolveSegment(obj: any, segment: string): any { if (obj == null || typeof obj !== "object") return undefined; + // Direct property access if (segment in obj) { return obj[segment]; } - // Check $children for objects that contain the segment - const children = obj["$children"]; + // Check if this is a special property name that matches the config + if (segment === this.config.propNames.value || + segment === this.config.propNames.children || + segment === this.config.propNames.attributes || + segment === this.config.propNames.namespace || + segment === this.config.propNames.prefix || + segment === this.config.propNames.cdata || + segment === this.config.propNames.comments || + segment === this.config.propNames.instruction || + segment === this.config.propNames.target) { + const configKey = Object.entries(this.config.propNames) + .find(([_, value]) => value === segment)?.[0]; + + if (configKey && obj[segment] !== undefined) { + return obj[segment]; + } + } + + // Check children for objects that contain the segment + const childrenKey = this.config.propNames.children; + const children = obj[childrenKey]; if (Array.isArray(children)) { const matches = children .map((child) => (segment in child ? child[segment] : undefined)) @@ -77,7 +109,7 @@ export class JSONUtil { * @param root Optional root element configuration (either a string or object with $ keys) * @returns XML-like JSON object */ - static fromJSONObject(obj: any, root?: any): any { + fromJSONObject(obj: any, root?: any): any { const wrappedObject = this.wrapObject(obj); if (typeof root === "string") { @@ -86,34 +118,37 @@ export class JSONUtil { } if (root && typeof root === "object") { - // Handle root with $ keys like $ns, $pre, $attrs + // Handle root with config-based keys const elementName = root.name || "root"; // Default to "root" if no name is provided - const prefix = root.$pre || ""; + const prefix = root[this.config.propNames.prefix] || ""; const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName; const result: any = { [qualifiedName]: {}, }; - // Add $attrs to the root element if defined - if (root.$attrs && Array.isArray(root.$attrs)) { - result[qualifiedName].$attrs = root.$attrs; + // Add attributes to the root element if defined + const attrsKey = this.config.propNames.attributes; + if (root[attrsKey] && Array.isArray(root[attrsKey])) { + result[qualifiedName][attrsKey] = root[attrsKey]; } - // Merge existing $children with the new generated children - const children = root.$children ? root.$children : []; - result[qualifiedName].$children = [ + // Merge existing children with the new generated children + const childrenKey = this.config.propNames.children; + const children = root[childrenKey] ? root[childrenKey] : []; + result[qualifiedName][childrenKey] = [ ...children, { [elementName]: wrappedObject }, ]; // Add namespace and prefix if defined - if (root.$ns) { - result[qualifiedName].$ns = root.$ns; + const nsKey = this.config.propNames.namespace; + if (root[nsKey]) { + result[qualifiedName][nsKey] = root[nsKey]; } - if (prefix && root.$ns) { - result[qualifiedName][`xmlns:${prefix}`] = root.$ns; + if (prefix && root[nsKey]) { + result[qualifiedName][`xmlns:${prefix}`] = root[nsKey]; } return result; @@ -128,32 +163,35 @@ export class JSONUtil { * @param value Value to wrap * @returns Wrapped value */ - private static wrapObject(value: any): any { + private wrapObject(value: any): any { + const valKey = this.config.propNames.value; + const childrenKey = this.config.propNames.children; + if ( value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" ) { - return { $val: value }; + return { [valKey]: value }; } if (Array.isArray(value)) { - // For arrays, wrap each item and return as a $children-style array of repeated elements + // For arrays, wrap each item and return as a children-style array of repeated elements return { - $children: value.map((item) => { + [childrenKey]: value.map((item) => { return this.wrapObject(item); }), }; } if (typeof value === "object") { - // It's an object: wrap its properties in $children + // It's an object: wrap its properties in children const children = Object.entries(value).map(([key, val]) => ({ [key]: this.wrapObject(val), })); - return { $children: children }; + return { [childrenKey]: children }; } return undefined; // Fallback for unhandled types @@ -164,7 +202,7 @@ export class JSONUtil { * @param value Value to check * @returns true if empty */ - static isEmpty(value: any): boolean { + isEmpty(value: any): boolean { if (value == null) return true; if (Array.isArray(value)) return value.length === 0; if (typeof value === 'object') return Object.keys(value).length === 0; @@ -177,7 +215,7 @@ export class JSONUtil { * @param indent Optional indentation level * @returns JSON string representation */ - static safeStringify(obj: any, indent: number = 2): string { + safeStringify(obj: any, indent: number = 2): string { try { return JSON.stringify(obj, null, indent); } catch (error) { @@ -190,7 +228,7 @@ export class JSONUtil { * @param obj Object to clone * @returns Cloned object */ - static deepClone(obj: any): any { + deepClone(obj: any): any { try { return JSON.parse(JSON.stringify(obj)); } catch (error) { @@ -204,7 +242,7 @@ export class JSONUtil { * @param source Source object * @returns Merged object (target is modified) */ - static deepMerge(target: any, source: any): any { + deepMerge(target: any, source: any): any { if (typeof source !== 'object' || source === null) { return target; } diff --git a/src/core/utils/XMLUtil.ts b/src/core/utils/XMLUtil.ts index 66f5bb8..96ca78d 100644 --- a/src/core/utils/XMLUtil.ts +++ b/src/core/utils/XMLUtil.ts @@ -3,15 +3,26 @@ */ import { XMLToJSONError } from "../types/errors"; import { DOMAdapter } from "../DOMAdapter"; +import { Configuration } from "../types/types"; export class XMLUtil { + private config: Configuration; + + /** + * Constructor for XMLUtil + * @param config Configuration options + */ + constructor(config: Configuration) { + this.config = config; + } + /** * Pretty print an XML string * @param xmlString XML string to format - * @param indent Number of spaces for indentation * @returns Formatted XML string */ - static prettyPrintXml(xmlString: string, indent: number = 2): string { + prettyPrintXml(xmlString: string): string { + const indent = this.config.outputOptions.indent; const INDENT = " ".repeat(indent); try { @@ -89,7 +100,7 @@ export class XMLUtil { * @param xmlString XML string to validate * @returns Object with validation result and any error messages */ - static validateXML(xmlString: string): { + validateXML(xmlString: string): { isValid: boolean; message?: string; } { @@ -116,7 +127,7 @@ export class XMLUtil { * @param xmlString XML string * @returns XML string with declaration */ - static ensureXMLDeclaration(xmlString: string): string { + ensureXMLDeclaration(xmlString: string): string { if (!xmlString.trim().startsWith("\n' + xmlString; } @@ -128,7 +139,7 @@ export class XMLUtil { * @param text Text to escape. * @returns Escaped XML string. */ - static escapeXML(text: string): string { + escapeXML(text: string): string { if (typeof text !== "string" || text.length === 0) { return ""; } @@ -156,7 +167,7 @@ export class XMLUtil { * @param text Text with XML entities. * @returns Unescaped text. */ - static unescapeXML(text: string): string { + unescapeXML(text: string): string { if (typeof text !== "string" || text.length === 0) { return ""; } @@ -184,7 +195,7 @@ export class XMLUtil { * @param qualifiedName Qualified name (e.g., "ns:element") * @returns Prefix or null if no prefix */ - static extractPrefix(qualifiedName: string): string | null { + extractPrefix(qualifiedName: string): string | null { const colonIndex = qualifiedName.indexOf(":"); return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null; } @@ -194,7 +205,7 @@ export class XMLUtil { * @param qualifiedName Qualified name (e.g., "ns:element") * @returns Local name */ - static extractLocalName(qualifiedName: string): string { + extractLocalName(qualifiedName: string): string { const colonIndex = qualifiedName.indexOf(":"); return colonIndex > 0 ? qualifiedName.substring(colonIndex + 1) @@ -207,7 +218,7 @@ export class XMLUtil { * @param localName Local name * @returns Qualified name */ - static createQualifiedName(prefix: string | null, localName: string): string { + createQualifiedName(prefix: string | null, localName: string): string { return prefix ? `${prefix}:${localName}` : localName; } -} +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 38d5507..f038c2f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import { XJX } from "./XJX"; import { XMLToJSON } from "./core/XMLToJSON"; import { JSONToXML } from "./core/JSONToXML"; import { DOMAdapter } from "./core/DOMAdapter"; -import { XMLToJSONConfig } from "./core/types/types"; +import { Configuration } from "./core/types/types"; import { DEFAULT_CONFIG } from "./core/config/config"; import { JSONUtil } from "./core/utils/JSONUtil"; import { XMLUtil } from "./core/utils/XMLUtil"; @@ -18,7 +18,7 @@ export { XMLToJSON, JSONToXML, DOMAdapter, - XMLToJSONConfig, + Configuration as XMLToJSONConfig, DEFAULT_CONFIG, JSONUtil, XMLUtil, From 83c4c26e98edcae075554cbb197e332e318a4152 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 18:58:05 -0500 Subject: [PATCH 16/38] fixed whitespace handling when preservewhitespace is false added escapeXML to text node creation --- src/core/JSONToXML.ts | 2 +- src/core/XMLToJSON.ts | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/core/JSONToXML.ts b/src/core/JSONToXML.ts index 86b5fa3..512dabe 100644 --- a/src/core/JSONToXML.ts +++ b/src/core/JSONToXML.ts @@ -168,7 +168,7 @@ export class JSONToXML { this.config.preserveTextNodes ) { element.appendChild( - DOMAdapter.createTextNode(child[valueKey]) + DOMAdapter.createTextNode(this.xmlUtil.escapeXML(child[valueKey])) ); } // CDATA sections diff --git a/src/core/XMLToJSON.ts b/src/core/XMLToJSON.ts index ca90271..9ce75c6 100644 --- a/src/core/XMLToJSON.ts +++ b/src/core/XMLToJSON.ts @@ -135,11 +135,15 @@ export class XMLToJSON { // Text nodes - only process if preserveTextNodes is true if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) { if (this.config.preserveTextNodes) { - const text = child.nodeValue || ""; + let text = child.nodeValue || ""; // Skip whitespace-only text nodes if whitespace preservation is disabled - if (!this.config.preserveWhitespace && text.trim() === "") { - continue; + if (!this.config.preserveWhitespace) { + if (text.trim() === "") { + continue; + } + // Trim the text when preserveWhitespace is false + text = text.trim(); } children.push({ [valueKey]: text }); @@ -241,7 +245,8 @@ export class XMLToJSON { const keys = Object.keys(node); if ( keys.every((key) => key === childrenKey || key === attrsKey) && - (node[childrenKey] === undefined || this.jsonUtil.isEmpty(node[childrenKey])) && + (node[childrenKey] === undefined || + this.jsonUtil.isEmpty(node[childrenKey])) && (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey])) ) { return undefined; @@ -252,4 +257,4 @@ export class XMLToJSON { return node; } -} \ No newline at end of file +} From a7cb1176ee5e180b80791d85cb93f9d89e3f4f53 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 19:55:30 -0500 Subject: [PATCH 17/38] updated tests --- test/{XJX.test.ts => XJX.test.js} | 69 ++++++- test/core/DOMAdapter.test.js | 9 +- test/core/JSONToXML.test.js | 318 ++++++++++++++++++++++++++++++ test/core/XMLToJSON.test.js | 173 ++++++++++++++++ test/core/utils/JSONUtil.test.js | 119 ++++++----- test/core/utils/XMLUtil.test.js | 75 ++++--- test/utils/testConfig.js | 49 +++++ 7 files changed, 732 insertions(+), 80 deletions(-) rename test/{XJX.test.ts => XJX.test.js} (66%) create mode 100644 test/core/JSONToXML.test.js create mode 100644 test/core/XMLToJSON.test.js create mode 100644 test/utils/testConfig.js diff --git a/test/XJX.test.ts b/test/XJX.test.js similarity index 66% rename from test/XJX.test.ts rename to test/XJX.test.js index 6eeb071..4a02278 100644 --- a/test/XJX.test.ts +++ b/test/XJX.test.js @@ -2,13 +2,16 @@ * XJX library tests */ import { XJX } from '../src/XJX'; +import { createTestConfig, cloneConfig } from './utils/testConfig'; describe('XJX', () => { let xjx: XJX; + let testConfig = createTestConfig(); beforeEach(() => { - // Create a fresh XJX instance before each test - xjx = new XJX(); + // Create a fresh XJX instance before each test with a clone of our test config + // This ensures no test can modify the config and affect other tests + xjx = new XJX(cloneConfig(testConfig)); }); afterEach(() => { @@ -58,6 +61,24 @@ describe('XJX', () => { expect(result.root.$children[0]).toHaveProperty('$cmnt', ' This is a comment '); }); + + it('should disable namespace handling when configured', () => { + // Create special instance for this test with modified config + const customConfig = cloneConfig(testConfig); + customConfig.preserveNamespaces = false; + const customXjx = new XJX(customConfig); + + const xml = 'Test'; + const result = customXjx.xmlToJson(xml); + + // The namespace and prefix properties should not be present + expect(result.root).not.toHaveProperty('$ns'); + expect(result.root.$children[0].item).not.toHaveProperty('$ns'); + expect(result.root.$children[0].item).not.toHaveProperty('$pre'); + + // Clean up + customXjx.cleanup(); + }); }); describe('jsonToXml', () => { @@ -106,6 +127,21 @@ describe('XJX', () => { const result = xjx.jsonToXml(json); expect(result).toContain('Test'); }); + + it('should exclude XML declaration when configured', () => { + // Create special instance for this test with modified config + const customConfig = cloneConfig(testConfig); + customConfig.outputOptions.xml.declaration = false; + const customXjx = new XJX(customConfig); + + const json = { root: { $val: 'Test' } }; + const result = customXjx.jsonToXml(json); + + expect(result).not.toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); + + // Clean up + customXjx.cleanup(); + }); }); describe('getPath', () => { @@ -167,4 +203,33 @@ describe('XJX', () => { expect(result.message).toBeDefined(); }); }); + + describe('configuration with custom property names', () => { + it('should work with custom property names for XML tokens', () => { + // Create special instance for this test with custom property names + const customConfig = cloneConfig(testConfig); + customConfig.propNames = { + namespace: "_namespace", + prefix: "_prefix", + attributes: "_attrs", + value: "_value", + cdata: "_cdata", + comments: "_comment", + instruction: "_pi", + target: "_target", + children: "_children" + }; + const customXjx = new XJX(customConfig); + + // Test XML to JSON with custom properties + const xml = 'Test'; + const result = customXjx.xmlToJson(xml); + + expect(result.root._children[0].item).toHaveProperty('_attrs'); + expect(result.root._children[0].item._attrs[0].id).toHaveProperty('_value', '123'); + + // Clean up + customXjx.cleanup(); + }); + }); }); \ No newline at end of file diff --git a/test/core/DOMAdapter.test.js b/test/core/DOMAdapter.test.js index 4742aed..9de6b0c 100644 --- a/test/core/DOMAdapter.test.js +++ b/test/core/DOMAdapter.test.js @@ -3,8 +3,13 @@ */ import { DOMAdapter } from '../../src/core/DOMAdapter'; import { XMLToJSONError } from '../../src/errors'; +import { createTestConfig } from '../utils/testConfig'; describe('DOMAdapter', () => { + // We don't directly pass the config to DOMAdapter, + // but creating it ensures consistent test environment + const testConfig = createTestConfig(); + afterEach(() => { // Clean up after each test to prevent memory leaks DOMAdapter.cleanup(); @@ -44,7 +49,7 @@ describe('DOMAdapter', () => { it('should create new documents', () => { const doc = DOMAdapter.createDocument(); - expect(doc.nodeType).toBe(document.DOCUMENT_NODE); + expect(doc.nodeType).toBe(DOMAdapter.nodeTypes.DOCUMENT_NODE); }); it('should create elements', () => { @@ -163,7 +168,7 @@ describe('DOMAdapter', () => { fail('Should have thrown an error'); } catch (error) { expect(error).toBeInstanceOf(XMLToJSONError); - expect((error as Error).message).toContain('Failed to parse XML'); + expect(error.message).toContain('Failed to parse XML'); } }); }); diff --git a/test/core/JSONToXML.test.js b/test/core/JSONToXML.test.js new file mode 100644 index 0000000..dc9baf9 --- /dev/null +++ b/test/core/JSONToXML.test.js @@ -0,0 +1,318 @@ +/** + * Tests for JSONToXML class + */ +import { JSONToXML } from '../../src/core/JSONToXML'; +import { XMLToJSON } from '../../src/core/XMLToJSON'; +import { createTestConfig, cloneConfig } from '../utils/testConfig'; +import { DOMAdapter } from '../../src/core/DOMAdapter'; + +describe('JSONToXML', () => { + let jsonToXML; + let xmlToJSON; + const testConfig = createTestConfig(); + + beforeEach(() => { + // Create fresh instances before each test with a clone of our test config + jsonToXML = new JSONToXML(cloneConfig(testConfig)); + xmlToJSON = new XMLToJSON(cloneConfig(testConfig)); + }); + + afterEach(() => { + // Clean up DOM resources + DOMAdapter.cleanup(); + }); + + describe('serialize', () => { + it('should convert a simple JSON object to XML', () => { + const json = { + root: { + [testConfig.propNames.children]: [ + { + item: { + [testConfig.propNames.value]: 'Test' + } + } + ] + } + }; + + const result = jsonToXML.serialize(json); + + expect(result).toContain(''); + expect(result).toContain('Test'); + expect(result).toContain(''); + }); + + it('should include XML declaration when enabled', () => { + const json = { root: { [testConfig.propNames.value]: 'Test' } }; + const result = jsonToXML.serialize(json); + + expect(result).toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); + }); + + it('should handle attributes', () => { + const json = { + root: { + [testConfig.propNames.children]: [ + { + item: { + [testConfig.propNames.attributes]: [ + { id: { [testConfig.propNames.value]: '123' } } + ], + [testConfig.propNames.value]: 'Test' + } + } + ] + } + }; + + const result = jsonToXML.serialize(json); + expect(result).toContain('Test'); + }); + + it('should handle namespaces when enabled', () => { + const json = { + root: { + [testConfig.propNames.namespace]: 'http://example.org', + [testConfig.propNames.children]: [ + { + item: { + [testConfig.propNames.namespace]: 'http://example.org', + [testConfig.propNames.prefix]: 'ns', + [testConfig.propNames.value]: 'Test' + } + } + ] + } + }; + + const result = jsonToXML.serialize(json); + + expect(result).toContain('xmlns="http://example.org"'); + expect(result).toContain(' { + const json = { + root: { + [testConfig.propNames.children]: [ + { + item: { + [testConfig.propNames.children]: [ + { [testConfig.propNames.cdata]: 'bold text' } + ] + } + } + ] + } + }; + + const result = jsonToXML.serialize(json); + + expect(result).toContain('bold text]]>'); + }); + + it('should handle comments when enabled', () => { + const json = { + root: { + [testConfig.propNames.children]: [ + { [testConfig.propNames.comments]: ' This is a comment ' }, + { + item: { + [testConfig.propNames.value]: 'Test' + } + } + ] + } + }; + + const result = jsonToXML.serialize(json); + + expect(result).toContain(''); + }); + + it('should handle processing instructions when enabled', () => { + const json = { + root: { + [testConfig.propNames.children]: [ + { + [testConfig.propNames.instruction]: { + [testConfig.propNames.target]: 'xml-stylesheet', + [testConfig.propNames.value]: 'type="text/css" href="style.css"' + } + }, + { + item: { + [testConfig.propNames.value]: 'Test' + } + } + ] + } + }; + + const result = jsonToXML.serialize(json); + + expect(result).toContain(''); + }); + + it('should handle nested elements', () => { + const json = { + root: { + [testConfig.propNames.children]: [ + { + parent: { + [testConfig.propNames.children]: [ + { + child: { + [testConfig.propNames.value]: 'Child Text' + } + } + ] + } + } + ] + } + }; + + const result = jsonToXML.serialize(json); + + expect(result).toContain(''); + expect(result).toContain('Child Text'); + expect(result).toContain(''); + }); + + it('should work with the XMLToJSON parser in a round-trip', () => { + const originalXml = ` + + + The Great Gatsby + F. Scott Fitzgerald + 1925 + + that should be preserved]]> + + + `; + + // XML -> JSON -> XML round trip + const json = xmlToJSON.parse(originalXml); + const resultXml = jsonToXML.serialize(json); + + // The resulting XML should have the same structure and content + expect(resultXml).toContain(''); + expect(resultXml).toContain(''); + expect(resultXml).toContain('The Great Gatsby'); + expect(resultXml).toContain('F. Scott Fitzgerald'); + expect(resultXml).toContain('1925'); + expect(resultXml).toContain(''); + expect(resultXml).toContain(' that should be preserved]]>'); + }); + }); + + describe('configuration tests', () => { + it('should not include XML declaration when disabled', () => { + const customConfig = cloneConfig(testConfig); + customConfig.outputOptions.xml.declaration = false; + const customJsonToXML = new JSONToXML(customConfig); + + const json = { root: { [testConfig.propNames.value]: 'Test' } }; + const result = customJsonToXML.serialize(json); + + expect(result).not.toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); + }); + + it('should not format XML (pretty print) when disabled', () => { + const customConfig = cloneConfig(testConfig); + customConfig.outputOptions.prettyPrint = false; + const customJsonToXML = new JSONToXML(customConfig); + + const json = { + root: { + [testConfig.propNames.children]: [ + { + item: { + [testConfig.propNames.children]: [ + { + nested: { + [testConfig.propNames.value]: 'Test' + } + } + ] + } + } + ] + } + }; + + const result = customJsonToXML.serialize(json); + + // The XML shouldn't contain formatting newlines and indentation + expect(result.split('\n').length).toBe(1); // Only the XML declaration might be on its own line + expect(result).not.toContain(' '); // No indentation + }); + + it('should not include namespaces when disabled', () => { + const customConfig = cloneConfig(testConfig); + customConfig.preserveNamespaces = false; + const customJsonToXML = new JSONToXML(customConfig); + + const json = { + root: { + [testConfig.propNames.namespace]: 'http://example.org', + [testConfig.propNames.children]: [ + { + item: { + [testConfig.propNames.namespace]: 'http://example.org', + [testConfig.propNames.prefix]: 'ns', + [testConfig.propNames.value]: 'Test' + } + } + ] + } + }; + + const result = customJsonToXML.serialize(json); + + // Namespaces should be ignored + expect(result).not.toContain('xmlns="http://example.org"'); + expect(result).not.toContain(' { + // Define custom property names + const customConfig = cloneConfig(testConfig); + customConfig.propNames = { + namespace: "_ns", + prefix: "_pre", + attributes: "_attrs", + value: "_val", + cdata: "_cdata", + comments: "_comment", + instruction: "_pi", + target: "_target", + children: "_children" + }; + + const customJsonToXML = new JSONToXML(customConfig); + + const json = { + root: { + "_children": [ + { + item: { + "_attrs": [ + { id: { "_val": "123" } } + ], + "_val": "Test" + } + } + ] + } + }; + + const result = customJsonToXML.serialize(json); + + expect(result).toContain('Test'); + }); + }); +}); \ No newline at end of file diff --git a/test/core/XMLToJSON.test.js b/test/core/XMLToJSON.test.js new file mode 100644 index 0000000..f3b62fc --- /dev/null +++ b/test/core/XMLToJSON.test.js @@ -0,0 +1,173 @@ +/** + * Tests for XMLToJSON class + */ +import { XMLToJSON } from '../../src/core/XMLToJSON'; +import { createTestConfig, cloneConfig } from '../utils/testConfig'; + +describe('XMLToJSON', () => { + let xmlToJSON; + const testConfig = createTestConfig(); + + beforeEach(() => { + // Create a fresh XMLToJSON instance before each test with a clone of our test config + xmlToJSON = new XMLToJSON(cloneConfig(testConfig)); + }); + + describe('parse', () => { + it('should convert a simple XML string to JSON', () => { + const xml = 'Test'; + const result = xmlToJSON.parse(xml); + + expect(result).toHaveProperty('root'); + expect(result.root).toHaveProperty(testConfig.propNames.children); + expect(result.root[testConfig.propNames.children][0]).toHaveProperty('item'); + expect(result.root[testConfig.propNames.children][0].item).toHaveProperty(testConfig.propNames.value, 'Test'); + }); + + it('should handle XML attributes', () => { + const xml = 'Test'; + const result = xmlToJSON.parse(xml); + + expect(result.root[testConfig.propNames.children][0].item).toHaveProperty(testConfig.propNames.attributes); + + const attrs = result.root[testConfig.propNames.children][0].item[testConfig.propNames.attributes]; + const idAttr = attrs.find(attr => attr.id); + const activeAttr = attrs.find(attr => attr.active); + + expect(idAttr.id[testConfig.propNames.value]).toBe('123'); + expect(activeAttr.active[testConfig.propNames.value]).toBe('true'); + }); + + it('should handle namespaces when enabled', () => { + const xml = 'Test'; + const result = xmlToJSON.parse(xml); + + expect(result.root).toHaveProperty(testConfig.propNames.namespace); + expect(result.root[testConfig.propNames.children][0].item).toHaveProperty(testConfig.propNames.namespace, 'http://example.org'); + expect(result.root[testConfig.propNames.children][0].item).toHaveProperty(testConfig.propNames.prefix, 'ns'); + }); + + it('should handle CDATA sections', () => { + const xml = 'bold text]]>'; + const result = xmlToJSON.parse(xml); + + expect(result.root[testConfig.propNames.children][0].item[testConfig.propNames.children][0]).toHaveProperty( + testConfig.propNames.cdata, + 'bold text' + ); + }); + + it('should handle comments when enabled', () => { + const xml = 'Test'; + const result = xmlToJSON.parse(xml); + + expect(result.root[testConfig.propNames.children][0]).toHaveProperty( + testConfig.propNames.comments, + ' This is a comment ' + ); + }); + + it('should handle processing instructions when enabled', () => { + const xml = 'Test'; + const result = xmlToJSON.parse(xml); + + const piElement = result.root[testConfig.propNames.children].find( + child => child[testConfig.propNames.instruction] + ); + + expect(piElement).toBeDefined(); + expect(piElement[testConfig.propNames.instruction][testConfig.propNames.target]).toBe('xml-stylesheet'); + expect(piElement[testConfig.propNames.instruction][testConfig.propNames.value]).toBe('type="text/css" href="style.css"'); + }); + + it('should handle nested elements', () => { + const xml = 'Child Text'; + const result = xmlToJSON.parse(xml); + + expect(result.root[testConfig.propNames.children][0].parent[testConfig.propNames.children][0].child) + .toHaveProperty(testConfig.propNames.value, 'Child Text'); + }); + + it('should handle empty elements', () => { + const xml = ''; + const result = xmlToJSON.parse(xml); + + const children = result.root[testConfig.propNames.children]; + const emptyElement = children.find(child => child.empty); + const selfClosingElement = children.find(child => child['self-closing']); + + expect(emptyElement).toBeDefined(); + expect(selfClosingElement).toBeDefined(); + }); + }); + + describe('configuration tests', () => { + it('should not preserve namespaces when disabled', () => { + const customConfig = cloneConfig(testConfig); + customConfig.preserveNamespaces = false; + const customXmlToJSON = new XMLToJSON(customConfig); + + const xml = 'Test'; + const result = customXmlToJSON.parse(xml); + + expect(result.root).not.toHaveProperty(testConfig.propNames.namespace); + expect(result.root[testConfig.propNames.children][0].item).not.toHaveProperty(testConfig.propNames.namespace); + expect(result.root[testConfig.propNames.children][0].item).not.toHaveProperty(testConfig.propNames.prefix); + }); + + it('should not preserve comments when disabled', () => { + const customConfig = cloneConfig(testConfig); + customConfig.preserveComments = false; + const customXmlToJSON = new XMLToJSON(customConfig); + + const xml = 'Test'; + const result = customXmlToJSON.parse(xml); + + const hasComment = result.root[testConfig.propNames.children].some( + child => child[testConfig.propNames.comments] + ); + + expect(hasComment).toBe(false); + }); + + it('should not preserve CDATA sections when disabled', () => { + const customConfig = cloneConfig(testConfig); + customConfig.preserveCDATA = false; + const customXmlToJSON = new XMLToJSON(customConfig); + + const xml = 'bold text]]>'; + const result = customXmlToJSON.parse(xml); + + const hasCDATA = result.root[testConfig.propNames.children][0].item[testConfig.propNames.children]?.some( + child => child[testConfig.propNames.cdata] + ); + + expect(hasCDATA).toBeFalsy(); + }); + + it('should use custom property names when configured', () => { + const customConfig = cloneConfig(testConfig); + customConfig.propNames = { + namespace: "_ns", + prefix: "_pre", + attributes: "_attrs", + value: "_val", + cdata: "_cdata", + comments: "_comment", + instruction: "_pi", + target: "_target", + children: "_children" + }; + + const customXmlToJSON = new XMLToJSON(customConfig); + + const xml = 'Test'; + const result = customXmlToJSON.parse(xml); + + expect(result.root).toHaveProperty('_children'); + expect(result.root._children[0].item).toHaveProperty('_attrs'); + expect(result.root._children[0].item).toHaveProperty('_val', 'Test'); + expect(result.root._children[0].item._attrs[0].id).toHaveProperty('_val', '123'); + }); + }); +}); \ No newline at end of file diff --git a/test/core/utils/JSONUtil.test.js b/test/core/utils/JSONUtil.test.js index ca31596..d54d205 100644 --- a/test/core/utils/JSONUtil.test.js +++ b/test/core/utils/JSONUtil.test.js @@ -1,9 +1,18 @@ /** * Tests for JSONUtil class */ -import { JSONUtil } from '../../../src/core/JSONUtil'; +import { JSONUtil } from '../../../src/core/utils/JSONUtil'; +import { createTestConfig, cloneConfig } from '../../utils/testConfig'; describe('JSONUtil', () => { + let jsonUtil; + const testConfig = createTestConfig(); + + beforeEach(() => { + // Create a fresh JSONUtil instance with a clone of our test config + jsonUtil = new JSONUtil(cloneConfig(testConfig)); + }); + describe('getPath', () => { it('should retrieve values using dot notation', () => { const json = { @@ -15,8 +24,8 @@ describe('JSONUtil', () => { } }; - expect(JSONUtil.getPath(json, 'user.name')).toBe('John'); - expect(JSONUtil.getPath(json, 'user.contact.email')).toBe('john@example.com'); + expect(jsonUtil.getPath(json, 'user.name')).toBe('John'); + expect(jsonUtil.getPath(json, 'user.contact.email')).toBe('john@example.com'); }); it('should traverse arrays automatically', () => { @@ -27,7 +36,7 @@ describe('JSONUtil', () => { ] }; - const names = JSONUtil.getPath(json, 'users.name'); + const names = jsonUtil.getPath(json, 'users.name'); expect(Array.isArray(names)).toBe(true); expect(names).toEqual(['John', 'Jane']); }); @@ -35,21 +44,24 @@ describe('JSONUtil', () => { it('should return fallback value when path does not exist', () => { const json = { user: { name: "John" } }; - expect(JSONUtil.getPath(json, 'user.age', 30)).toBe(30); - expect(JSONUtil.getPath(json, 'company.name', 'Unknown')).toBe('Unknown'); + expect(jsonUtil.getPath(json, 'user.age', 30)).toBe(30); + expect(jsonUtil.getPath(json, 'company.name', 'Unknown')).toBe('Unknown'); }); it('should handle XML-like JSON structures', () => { + const childrenKey = testConfig.propNames.children; + const valKey = testConfig.propNames.value; + const json = { root: { - $children: [ - { item: { $val: "Item 1" } }, - { item: { $val: "Item 2" } } + [childrenKey]: [ + { item: { [valKey]: "Item 1" } }, + { item: { [valKey]: "Item 2" } } ] } }; - expect(JSONUtil.getPath(json, 'root.$children.item.$val')).toEqual(["Item 1", "Item 2"]); + expect(jsonUtil.getPath(json, `root.${childrenKey}.item.${valKey}`)).toEqual(["Item 1", "Item 2"]); }); it('should collapse singleton arrays', () => { @@ -59,7 +71,7 @@ describe('JSONUtil', () => { } }; - expect(JSONUtil.getPath(json, 'user.roles')).toBe('admin'); + expect(jsonUtil.getPath(json, 'user.roles')).toBe('admin'); }); }); @@ -70,20 +82,23 @@ describe('JSONUtil', () => { age: 30 }; - const result = JSONUtil.fromJSONObject(json); + const result = jsonUtil.fromJSONObject(json); + const childrenKey = testConfig.propNames.children; + const valKey = testConfig.propNames.value; - expect(result).toHaveProperty('$children'); - expect(result.$children).toHaveLength(2); - expect(result.$children[0].name).toHaveProperty('$val', 'John'); - expect(result.$children[1].age).toHaveProperty('$val', 30); + expect(result).toHaveProperty(childrenKey); + expect(result[childrenKey]).toHaveLength(2); + expect(result[childrenKey][0].name).toHaveProperty(valKey, 'John'); + expect(result[childrenKey][1].age).toHaveProperty(valKey, 30); }); it('should wrap result in a root element if provided', () => { const json = { name: "John" }; - const result = JSONUtil.fromJSONObject(json, "user"); + const result = jsonUtil.fromJSONObject(json, "user"); + const childrenKey = testConfig.propNames.children; expect(result).toHaveProperty('user'); - expect(result.user).toHaveProperty('$children'); + expect(result.user).toHaveProperty(childrenKey); }); it('should handle arrays correctly', () => { @@ -91,78 +106,86 @@ describe('JSONUtil', () => { items: ["A", "B", "C"] }; - const result = JSONUtil.fromJSONObject(json); - expect(result.$children[0].items).toHaveProperty('$children'); - expect(result.$children[0].items.$children).toHaveLength(3); - expect(result.$children[0].items.$children[0]).toHaveProperty('$val', 'A'); + const result = jsonUtil.fromJSONObject(json); + const childrenKey = testConfig.propNames.children; + const valKey = testConfig.propNames.value; + + expect(result[childrenKey][0].items).toHaveProperty(childrenKey); + expect(result[childrenKey][0].items[childrenKey]).toHaveLength(3); + expect(result[childrenKey][0].items[childrenKey][0]).toHaveProperty(valKey, 'A'); }); it('should handle complex root configuration', () => { + const nsKey = testConfig.propNames.namespace; + const preKey = testConfig.propNames.prefix; + const attrKey = testConfig.propNames.attributes; + const valKey = testConfig.propNames.value; + const json = { name: "John" }; - const result = JSONUtil.fromJSONObject(json, { + const result = jsonUtil.fromJSONObject(json, { name: "user", - $pre: "ns", - $ns: "http://example.org", - $attrs: [ - { id: { $val: "u1" } } + [preKey]: "ns", + [nsKey]: "http://example.org", + [attrKey]: [ + { id: { [valKey]: "u1" } } ] }); expect(result).toHaveProperty('ns:user'); - expect(result['ns:user']).toHaveProperty('$ns', 'http://example.org'); - expect(result['ns:user']).toHaveProperty('$attrs'); - expect(result['ns:user'].$attrs[0].id).toHaveProperty('$val', 'u1'); + expect(result['ns:user']).toHaveProperty(nsKey, 'http://example.org'); + expect(result['ns:user']).toHaveProperty(attrKey); + expect(result['ns:user'][attrKey][0].id).toHaveProperty(valKey, 'u1'); }); }); describe('isEmpty', () => { it('should return true for null and undefined', () => { - expect(JSONUtil.isEmpty(null)).toBe(true); - expect(JSONUtil.isEmpty(undefined)).toBe(true); + expect(jsonUtil.isEmpty(null)).toBe(true); + expect(jsonUtil.isEmpty(undefined)).toBe(true); }); it('should return true for empty arrays', () => { - expect(JSONUtil.isEmpty([])).toBe(true); + expect(jsonUtil.isEmpty([])).toBe(true); }); it('should return true for empty objects', () => { - expect(JSONUtil.isEmpty({})).toBe(true); + expect(jsonUtil.isEmpty({})).toBe(true); }); it('should return false for non-empty arrays', () => { - expect(JSONUtil.isEmpty([1, 2, 3])).toBe(false); + expect(jsonUtil.isEmpty([1, 2, 3])).toBe(false); }); it('should return false for non-empty objects', () => { - expect(JSONUtil.isEmpty({ key: 'value' })).toBe(false); + expect(jsonUtil.isEmpty({ key: 'value' })).toBe(false); }); it('should return false for primitive values', () => { - expect(JSONUtil.isEmpty(0)).toBe(false); - expect(JSONUtil.isEmpty('')).toBe(false); - expect(JSONUtil.isEmpty(false)).toBe(false); + expect(jsonUtil.isEmpty(0)).toBe(false); + expect(jsonUtil.isEmpty('')).toBe(false); + expect(jsonUtil.isEmpty(false)).toBe(false); }); }); describe('safeStringify', () => { it('should stringify valid JSON objects', () => { const obj = { name: "John", age: 30 }; - const result = JSONUtil.safeStringify(obj); + const result = jsonUtil.safeStringify(obj); expect(result).toBe(JSON.stringify(obj, null, 2)); }); it('should handle circular references gracefully', () => { - const obj: any = { name: "John" }; + const obj = { name: "John" }; obj.self = obj; // Create circular reference - const result = JSONUtil.safeStringify(obj); + const result = jsonUtil.safeStringify(obj); expect(result).toBe('[Cannot stringify object]'); }); it('should respect custom indent', () => { const obj = { name: "John", age: 30 }; - const result = JSONUtil.safeStringify(obj, 4); + const result = jsonUtil.safeStringify(obj, 4); expect(result).toBe(JSON.stringify(obj, null, 4)); }); @@ -178,7 +201,7 @@ describe('JSONUtil', () => { tags: ["user", "admin"] }; - const clone = JSONUtil.deepClone(original); + const clone = jsonUtil.deepClone(original); expect(clone).toEqual(original); expect(clone).not.toBe(original); @@ -207,7 +230,7 @@ describe('JSONUtil', () => { } }; - const result = JSONUtil.deepMerge(target, source); + const result = jsonUtil.deepMerge(target, source); expect(result).toBe(target); // Should modify target expect(result.name).toBe("John"); @@ -222,14 +245,14 @@ describe('JSONUtil', () => { const target = { tags: ["user"] }; const source = { tags: ["admin"] }; - const result = JSONUtil.deepMerge(target, source); + const result = jsonUtil.deepMerge(target, source); expect(result.tags).toEqual(["admin"]); }); it('should handle null and undefined values', () => { - expect(JSONUtil.deepMerge({ name: "John" }, null)).toEqual({ name: "John" }); - expect(JSONUtil.deepMerge(null, { name: "John" })).toEqual({ name: "John" }); + expect(jsonUtil.deepMerge({ name: "John" }, null)).toEqual({ name: "John" }); + expect(jsonUtil.deepMerge(null, { name: "John" })).toEqual({ name: "John" }); }); }); }); \ No newline at end of file diff --git a/test/core/utils/XMLUtil.test.js b/test/core/utils/XMLUtil.test.js index 7200e48..0a5d821 100644 --- a/test/core/utils/XMLUtil.test.js +++ b/test/core/utils/XMLUtil.test.js @@ -1,14 +1,28 @@ /** * Tests for XMLUtil class */ -import { XMLUtil } from '../../../src/core/XMLUtil'; +import { XMLUtil } from '../../../src/core/utils/XMLUtil'; import { DOMAdapter } from '../../../src/core/DOMAdapter'; +import { createTestConfig, cloneConfig } from '../../utils/testConfig'; describe('XMLUtil', () => { + let xmlUtil; + const testConfig = createTestConfig(); + + beforeEach(() => { + // Create a fresh XMLUtil instance with a clone of our test config + xmlUtil = new XMLUtil(cloneConfig(testConfig)); + }); + + afterEach(() => { + // Clean up DOM resources + DOMAdapter.cleanup(); + }); + describe('prettyPrintXml', () => { it('should format XML with proper indentation', () => { const xml = 'Test123'; - const result = XMLUtil.prettyPrintXml(xml); + const result = xmlUtil.prettyPrintXml(xml); expect(result).toContain('\n'); expect(result).toContain(' '); @@ -17,14 +31,14 @@ describe('XMLUtil', () => { it('should handle XML with attributes', () => { const xml = 'Test'; - const result = XMLUtil.prettyPrintXml(xml); + const result = xmlUtil.prettyPrintXml(xml); expect(result).toContain(''); }); it('should handle empty elements correctly', () => { const xml = ''; - const result = XMLUtil.prettyPrintXml(xml); + const result = xmlUtil.prettyPrintXml(xml); expect(result).toContain(''); expect(result).toContain(''); @@ -32,8 +46,13 @@ describe('XMLUtil', () => { }); it('should respect custom indentation', () => { + // Create a new XMLUtil instance with custom indentation + const customConfig = cloneConfig(testConfig); + customConfig.outputOptions.indent = 4; + const customXmlUtil = new XMLUtil(customConfig); + const xml = 'Test'; - const result = XMLUtil.prettyPrintXml(xml, 4); + const result = customXmlUtil.prettyPrintXml(xml); expect(result).toContain('\n'); expect(result).toContain(' '); @@ -44,7 +63,7 @@ describe('XMLUtil', () => { describe('validateXML', () => { it('should return true for valid XML', () => { const xml = 'Test'; - const result = XMLUtil.validateXML(xml); + const result = xmlUtil.validateXML(xml); expect(result.isValid).toBe(true); expect(result.message).toBeUndefined(); @@ -52,7 +71,7 @@ describe('XMLUtil', () => { it('should return false for XML with unclosed tags', () => { const xml = 'Test'; - const result = XMLUtil.validateXML(xml); + const result = xmlUtil.validateXML(xml); expect(result.isValid).toBe(false); expect(result.message).toBeDefined(); @@ -60,7 +79,7 @@ describe('XMLUtil', () => { it('should return false for XML with malformed attributes', () => { const xml = 'Test'; - const result = XMLUtil.validateXML(xml); + const result = xmlUtil.validateXML(xml); expect(result.isValid).toBe(false); expect(result.message).toBeDefined(); @@ -68,7 +87,7 @@ describe('XMLUtil', () => { it('should return false for non-XML content', () => { const xml = 'This is not XML'; - const result = XMLUtil.validateXML(xml); + const result = xmlUtil.validateXML(xml); expect(result.isValid).toBe(false); expect(result.message).toBeDefined(); @@ -78,7 +97,7 @@ describe('XMLUtil', () => { describe('ensureXMLDeclaration', () => { it('should add XML declaration if missing', () => { const xml = 'Test'; - const result = XMLUtil.ensureXMLDeclaration(xml); + const result = xmlUtil.ensureXMLDeclaration(xml); expect(result).toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); expect(result).toContain(''); @@ -86,14 +105,14 @@ describe('XMLUtil', () => { it('should not add XML declaration if already present', () => { const xml = 'Test'; - const result = XMLUtil.ensureXMLDeclaration(xml); + const result = xmlUtil.ensureXMLDeclaration(xml); expect(result).toBe(xml); }); it('should handle XML declaration with different attributes', () => { const xml = 'Test'; - const result = XMLUtil.ensureXMLDeclaration(xml); + const result = xmlUtil.ensureXMLDeclaration(xml); expect(result).toBe(xml); }); @@ -102,22 +121,22 @@ describe('XMLUtil', () => { describe('escapeXML & unescapeXML', () => { it('should escape special XML characters', () => { const input = 'Text & More'; - const result = XMLUtil.escapeXML(input); + const result = xmlUtil.escapeXML(input); expect(result).toBe('<tag attr="value">Text & More</tag>'); }); it('should unescape XML entities', () => { const input = '<tag attr="value">Text & More</tag>'; - const result = XMLUtil.unescapeXML(input); + const result = xmlUtil.unescapeXML(input); expect(result).toBe('Text & More'); }); it('should handle round-trip escape/unescape correctly', () => { const input = 'John & Jane'; - const escaped = XMLUtil.escapeXML(input); - const unescaped = XMLUtil.unescapeXML(escaped); + const escaped = xmlUtil.escapeXML(input); + const unescaped = xmlUtil.unescapeXML(escaped); expect(unescaped).toBe(input); }); @@ -125,35 +144,35 @@ describe('XMLUtil', () => { describe('extractPrefix & extractLocalName', () => { it('should extract namespace prefix from qualified name', () => { - expect(XMLUtil.extractPrefix('ns:element')).toBe('ns'); - expect(XMLUtil.extractPrefix('prefix:tag')).toBe('prefix'); + expect(xmlUtil.extractPrefix('ns:element')).toBe('ns'); + expect(xmlUtil.extractPrefix('prefix:tag')).toBe('prefix'); }); it('should return null for names without prefix', () => { - expect(XMLUtil.extractPrefix('element')).toBeNull(); - expect(XMLUtil.extractPrefix('tag')).toBeNull(); + expect(xmlUtil.extractPrefix('element')).toBeNull(); + expect(xmlUtil.extractPrefix('tag')).toBeNull(); }); it('should extract local name from qualified name', () => { - expect(XMLUtil.extractLocalName('ns:element')).toBe('element'); - expect(XMLUtil.extractLocalName('prefix:tag')).toBe('tag'); + expect(xmlUtil.extractLocalName('ns:element')).toBe('element'); + expect(xmlUtil.extractLocalName('prefix:tag')).toBe('tag'); }); it('should return the name itself for names without prefix', () => { - expect(XMLUtil.extractLocalName('element')).toBe('element'); - expect(XMLUtil.extractLocalName('tag')).toBe('tag'); + expect(xmlUtil.extractLocalName('element')).toBe('element'); + expect(xmlUtil.extractLocalName('tag')).toBe('tag'); }); }); describe('createQualifiedName', () => { it('should create qualified name with prefix', () => { - expect(XMLUtil.createQualifiedName('ns', 'element')).toBe('ns:element'); - expect(XMLUtil.createQualifiedName('prefix', 'tag')).toBe('prefix:tag'); + expect(xmlUtil.createQualifiedName('ns', 'element')).toBe('ns:element'); + expect(xmlUtil.createQualifiedName('prefix', 'tag')).toBe('prefix:tag'); }); it('should return only local name when prefix is null', () => { - expect(XMLUtil.createQualifiedName(null, 'element')).toBe('element'); - expect(XMLUtil.createQualifiedName(null, 'tag')).toBe('tag'); + expect(xmlUtil.createQualifiedName(null, 'element')).toBe('element'); + expect(xmlUtil.createQualifiedName(null, 'tag')).toBe('tag'); }); }); }); \ No newline at end of file diff --git a/test/utils/testConfig.js b/test/utils/testConfig.js new file mode 100644 index 0000000..844e6e6 --- /dev/null +++ b/test/utils/testConfig.js @@ -0,0 +1,49 @@ +/** + * Standard test configuration for XJX library tests + */ +import { Configuration } from '../../src/core/types/types'; + +/** + * Creates a standard test configuration to use across all tests + * This ensures tests are not affected by changes to the default configuration + */ +export const createTestConfig = (): Configuration => { + return { + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveWhitespace: false, + preserveAttributes: true, + + outputOptions: { + prettyPrint: true, + indent: 2, + compact: true, + json: {}, + xml: { + declaration: true, + }, + }, + + propNames: { + namespace: "$ns", + prefix: "$pre", + attributes: "$attr", + value: "$val", + cdata: "$cdata", + comments: "$cmnt", + instruction: "$pi", + target: "$trgt", + children: "$children", + }, + }; +}; + +/** + * Deep clone an object - useful for ensuring test isolation + */ +export const cloneConfig = (config: Configuration): Configuration => { + return JSON.parse(JSON.stringify(config)); +}; \ No newline at end of file From ed4c7105dd7e98fb262e097cfb3c4cf932fab4ba Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 20:48:55 -0500 Subject: [PATCH 18/38] test updates --- jest.config.js | 2 +- src/core/utils/XMLUtil.ts | 11 ++-- test/README.md | 59 ------------------- test/{XJX.test.js => XJX.test.ts} | 3 +- ...{DOMAdapter.test.js => DOMAdapter.test.ts} | 19 +----- .../{JSONToXML.test.js => JSONToXML.test.ts} | 7 ++- .../{XMLToJSON.test.js => XMLToJSON.test.ts} | 19 +++--- .../{JSONUtil.test.js => JSONUtil.test.ts} | 11 ++-- .../{XMLUtil.test.js => XMLUtil.test.ts} | 8 +-- test/jest.setup.js | 40 ------------- test/jest.setup.ts | 40 +++++++++++++ test/utils/{testConfig.js => testConfig.ts} | 0 12 files changed, 75 insertions(+), 144 deletions(-) delete mode 100644 test/README.md rename test/{XJX.test.js => XJX.test.ts} (98%) rename test/core/{DOMAdapter.test.js => DOMAdapter.test.ts} (88%) rename test/core/{JSONToXML.test.js => JSONToXML.test.ts} (98%) rename test/core/{XMLToJSON.test.js => XMLToJSON.test.ts} (90%) rename test/core/utils/{JSONUtil.test.js => JSONUtil.test.ts} (96%) rename test/core/utils/{XMLUtil.test.js => XMLUtil.test.ts} (97%) delete mode 100644 test/jest.setup.js create mode 100644 test/jest.setup.ts rename test/utils/{testConfig.js => testConfig.ts} (100%) diff --git a/jest.config.js b/jest.config.js index da1153a..c2110db 100644 --- a/jest.config.js +++ b/jest.config.js @@ -29,7 +29,7 @@ const config = { '/dist/' ], setupFilesAfterEnv: [ - '/test/jest.setup.js' + '/test/jest.setup.ts' ] }; diff --git a/src/core/utils/XMLUtil.ts b/src/core/utils/XMLUtil.ts index 96ca78d..b6b57d7 100644 --- a/src/core/utils/XMLUtil.ts +++ b/src/core/utils/XMLUtil.ts @@ -41,17 +41,20 @@ export class XMLUtil { const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`; const children = Array.from(el.childNodes); + if (children.length === 0) { return `${pad}${openTag.replace(/>$/, " />")}\n`; } // Single text node: print inline if ( - children.length === 1 && - children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE && - children[0].textContent?.trim() !== "" + children.length === 0 || + (children.length === 1 && + children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE && + children[0].textContent?.trim() === "") ) { - return `${pad}${openTag}${children[0].textContent}\n`; + // Empty or whitespace-only + return `${pad}<${tagName}${attrs ? " " + attrs : ""}>\n`; } const inner = children diff --git a/test/README.md b/test/README.md deleted file mode 100644 index dbd8190..0000000 --- a/test/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# XJX Library Tests - -This directory contains tests for the XJX library. The tests are written using Jest and run in a JSDOM environment to simulate browser behavior. - -## Test Structure - -- `XJX.test.ts` - Tests for the main facade class -- `utils/XMLUtil.test.ts` - Tests for XML utility functions -- `utils/JSONUtil.test.ts` - Tests for JSON utility functions -- `jest.setup.js` - Setup file for Jest testing environment - -## Running Tests - -To run the tests, use one of the following commands: - -```bash -# Run all tests -npm test - -# Run tests in watch mode (useful during development) -npm run test:watch - -# Generate coverage report -npm run test:coverage -``` - -## Writing Tests - -When writing tests for the XJX library, consider the following: - -1. Tests should be placed in this `/test` directory, mirroring the structure of the `/src` directory -2. Each test file should focus on testing a single class or module -3. Use descriptive test names following the pattern: `it('should do something when something happens')` -4. Use the JSDOM environment to test browser-specific functionality -5. Clean up resources after each test to prevent memory leaks - -## Test Environment - -The tests run in a JSDOM environment, which provides browser-like globals such as `window`, `document`, `DOMParser`, and `XMLSerializer`. This allows us to test DOM operations without a real browser. - -The `jest.setup.js` file configures the test environment and provides any necessary mocks for browser APIs that JSDOM doesn't implement. - -## Coverage Requirements - -New features should aim for at least 80% test coverage, with a focus on testing: - -1. Normal usage patterns -2. Edge cases and error handling -3. Configuration options -4. Cross-environment compatibility - -## Debugging Tests - -If you encounter issues with tests, you can use the following techniques: - -1. Run a single test file: `npx jest path/to/file.test.ts` -2. Debug a specific test: `npx jest -t "test name pattern" --runInBand` -3. Increase verbosity: `npx jest --verbose` -4. Debug in Node.js: Add `debugger` statements and run with `node --inspect-brk node_modules/.bin/jest --runInBand` \ No newline at end of file diff --git a/test/XJX.test.js b/test/XJX.test.ts similarity index 98% rename from test/XJX.test.js rename to test/XJX.test.ts index 4a02278..dc75643 100644 --- a/test/XJX.test.js +++ b/test/XJX.test.ts @@ -2,11 +2,12 @@ * XJX library tests */ import { XJX } from '../src/XJX'; +import { Configuration } from '../src/core/types/types'; import { createTestConfig, cloneConfig } from './utils/testConfig'; describe('XJX', () => { let xjx: XJX; - let testConfig = createTestConfig(); + let testConfig: Configuration = createTestConfig(); beforeEach(() => { // Create a fresh XJX instance before each test with a clone of our test config diff --git a/test/core/DOMAdapter.test.js b/test/core/DOMAdapter.test.ts similarity index 88% rename from test/core/DOMAdapter.test.js rename to test/core/DOMAdapter.test.ts index 9de6b0c..630367a 100644 --- a/test/core/DOMAdapter.test.js +++ b/test/core/DOMAdapter.test.ts @@ -2,7 +2,7 @@ * Tests for DOMAdapter */ import { DOMAdapter } from '../../src/core/DOMAdapter'; -import { XMLToJSONError } from '../../src/errors'; +import { XMLToJSONError } from '../../src/core/types/errors'; import { createTestConfig } from '../utils/testConfig'; describe('DOMAdapter', () => { @@ -155,21 +155,4 @@ describe('DOMAdapter', () => { }); }); }); - - describe('Error handling', () => { - it('should handle errors when parsing invalid XML', () => { - try { - // JSDOM's parser is quite forgiving, so we need to mock a parsing error - jest.spyOn(DOMAdapter, 'parseFromString').mockImplementationOnce(() => { - throw new Error('Mocked parsing error'); - }); - - DOMAdapter.parseFromString(''); - fail('Should have thrown an error'); - } catch (error) { - expect(error).toBeInstanceOf(XMLToJSONError); - expect(error.message).toContain('Failed to parse XML'); - } - }); - }); }); \ No newline at end of file diff --git a/test/core/JSONToXML.test.js b/test/core/JSONToXML.test.ts similarity index 98% rename from test/core/JSONToXML.test.js rename to test/core/JSONToXML.test.ts index dc9baf9..3857a6f 100644 --- a/test/core/JSONToXML.test.js +++ b/test/core/JSONToXML.test.ts @@ -3,13 +3,14 @@ */ import { JSONToXML } from '../../src/core/JSONToXML'; import { XMLToJSON } from '../../src/core/XMLToJSON'; +import { Configuration } from '../../src/core/types/types'; import { createTestConfig, cloneConfig } from '../utils/testConfig'; import { DOMAdapter } from '../../src/core/DOMAdapter'; describe('JSONToXML', () => { - let jsonToXML; - let xmlToJSON; - const testConfig = createTestConfig(); + let jsonToXML: JSONToXML; + let xmlToJSON: XMLToJSON; + const testConfig: Configuration = createTestConfig(); beforeEach(() => { // Create fresh instances before each test with a clone of our test config diff --git a/test/core/XMLToJSON.test.js b/test/core/XMLToJSON.test.ts similarity index 90% rename from test/core/XMLToJSON.test.js rename to test/core/XMLToJSON.test.ts index f3b62fc..e320c65 100644 --- a/test/core/XMLToJSON.test.js +++ b/test/core/XMLToJSON.test.ts @@ -2,11 +2,12 @@ * Tests for XMLToJSON class */ import { XMLToJSON } from '../../src/core/XMLToJSON'; +import { Configuration } from '../../src/core/types/types'; import { createTestConfig, cloneConfig } from '../utils/testConfig'; describe('XMLToJSON', () => { - let xmlToJSON; - const testConfig = createTestConfig(); + let xmlToJSON: XMLToJSON; + const testConfig: Configuration = createTestConfig(); beforeEach(() => { // Create a fresh XMLToJSON instance before each test with a clone of our test config @@ -31,8 +32,8 @@ describe('XMLToJSON', () => { expect(result.root[testConfig.propNames.children][0].item).toHaveProperty(testConfig.propNames.attributes); const attrs = result.root[testConfig.propNames.children][0].item[testConfig.propNames.attributes]; - const idAttr = attrs.find(attr => attr.id); - const activeAttr = attrs.find(attr => attr.active); + const idAttr = attrs.find((attr: Record) => attr.id); + const activeAttr = attrs.find((attr: Record) => attr.active); expect(idAttr.id[testConfig.propNames.value]).toBe('123'); expect(activeAttr.active[testConfig.propNames.value]).toBe('true'); @@ -72,7 +73,7 @@ describe('XMLToJSON', () => { const result = xmlToJSON.parse(xml); const piElement = result.root[testConfig.propNames.children].find( - child => child[testConfig.propNames.instruction] + (child: Record) => child[testConfig.propNames.instruction] ); expect(piElement).toBeDefined(); @@ -93,8 +94,8 @@ describe('XMLToJSON', () => { const result = xmlToJSON.parse(xml); const children = result.root[testConfig.propNames.children]; - const emptyElement = children.find(child => child.empty); - const selfClosingElement = children.find(child => child['self-closing']); + const emptyElement = children.find((child: Record) => child.empty); + const selfClosingElement = children.find((child: Record) => child['self-closing']); expect(emptyElement).toBeDefined(); expect(selfClosingElement).toBeDefined(); @@ -124,7 +125,7 @@ describe('XMLToJSON', () => { const result = customXmlToJSON.parse(xml); const hasComment = result.root[testConfig.propNames.children].some( - child => child[testConfig.propNames.comments] + (child: Record) => child[testConfig.propNames.comments] ); expect(hasComment).toBe(false); @@ -139,7 +140,7 @@ describe('XMLToJSON', () => { const result = customXmlToJSON.parse(xml); const hasCDATA = result.root[testConfig.propNames.children][0].item[testConfig.propNames.children]?.some( - child => child[testConfig.propNames.cdata] + (child: Record) => child[testConfig.propNames.cdata] ); expect(hasCDATA).toBeFalsy(); diff --git a/test/core/utils/JSONUtil.test.js b/test/core/utils/JSONUtil.test.ts similarity index 96% rename from test/core/utils/JSONUtil.test.js rename to test/core/utils/JSONUtil.test.ts index d54d205..6cafdeb 100644 --- a/test/core/utils/JSONUtil.test.js +++ b/test/core/utils/JSONUtil.test.ts @@ -2,11 +2,12 @@ * Tests for JSONUtil class */ import { JSONUtil } from '../../../src/core/utils/JSONUtil'; +import { Configuration } from '../../../src/core/types/types'; import { createTestConfig, cloneConfig } from '../../utils/testConfig'; describe('JSONUtil', () => { - let jsonUtil; - const testConfig = createTestConfig(); + let jsonUtil: JSONUtil; + const testConfig: Configuration = createTestConfig(); beforeEach(() => { // Create a fresh JSONUtil instance with a clone of our test config @@ -176,7 +177,7 @@ describe('JSONUtil', () => { }); it('should handle circular references gracefully', () => { - const obj = { name: "John" }; + const obj: Record = { name: "John" }; obj.self = obj; // Create circular reference const result = jsonUtil.safeStringify(obj); @@ -210,7 +211,7 @@ describe('JSONUtil', () => { }); it('should deep merge two objects', () => { - const target = { + const target: Record = { name: "John", contact: { email: "john@example.com" @@ -242,7 +243,7 @@ describe('JSONUtil', () => { }); it('should handle arrays during merge', () => { - const target = { tags: ["user"] }; + const target: Record = { tags: ["user"] }; const source = { tags: ["admin"] }; const result = jsonUtil.deepMerge(target, source); diff --git a/test/core/utils/XMLUtil.test.js b/test/core/utils/XMLUtil.test.ts similarity index 97% rename from test/core/utils/XMLUtil.test.js rename to test/core/utils/XMLUtil.test.ts index 0a5d821..0ead2fb 100644 --- a/test/core/utils/XMLUtil.test.js +++ b/test/core/utils/XMLUtil.test.ts @@ -3,11 +3,12 @@ */ import { XMLUtil } from '../../../src/core/utils/XMLUtil'; import { DOMAdapter } from '../../../src/core/DOMAdapter'; +import { Configuration } from '../../../src/core/types/types'; import { createTestConfig, cloneConfig } from '../../utils/testConfig'; describe('XMLUtil', () => { - let xmlUtil; - const testConfig = createTestConfig(); + let xmlUtil: XMLUtil; + const testConfig: Configuration = createTestConfig(); beforeEach(() => { // Create a fresh XMLUtil instance with a clone of our test config @@ -41,8 +42,7 @@ describe('XMLUtil', () => { const result = xmlUtil.prettyPrintXml(xml); expect(result).toContain(''); - expect(result).toContain(''); - expect(result).toContain(''); + expect(result).toContain(''); }); it('should respect custom indentation', () => { diff --git a/test/jest.setup.js b/test/jest.setup.js deleted file mode 100644 index 31459fc..0000000 --- a/test/jest.setup.js +++ /dev/null @@ -1,40 +0,0 @@ -// Jest setup file for the XJX library tests - -// JSDOM environment should already be set up by Jest's testEnvironment configuration, -// but we can add any additional mocks or configuration here if needed. - -// In case we need to mock any browser features that JSDOM doesn't provide -if (typeof window !== 'undefined') { - // If XMLSerializer isn't available in the JSDOM environment, mock it - if (!window.XMLSerializer) { - window.XMLSerializer = class XMLSerializer { - serializeToString(node) { - return `${node.nodeName}`; - } - }; - } - - // If DOMParser isn't available in the JSDOM environment, mock it - if (!window.DOMParser) { - window.DOMParser = class DOMParser { - parseFromString(xmlString, mimeType) { - const document = window.document.implementation.createDocument(null, 'root', null); - - // Create a basic document structure for testing - const mockElement = document.createElement('mockElement'); - mockElement.textContent = xmlString; - document.documentElement.appendChild(mockElement); - - return document; - } - }; - } - } - - // Silence console errors during tests to keep output clean - jest.spyOn(console, 'error').mockImplementation(() => {}); - - // Reset all mocks after each test - afterEach(() => { - jest.clearAllMocks(); - }); \ No newline at end of file diff --git a/test/jest.setup.ts b/test/jest.setup.ts new file mode 100644 index 0000000..f4057d5 --- /dev/null +++ b/test/jest.setup.ts @@ -0,0 +1,40 @@ +// Jest setup file for the XJX library tests + +// JSDOM environment should already be set up by Jest's testEnvironment configuration, +// but we can add any additional mocks or configuration here if needed. + +// In case we need to mock any browser features that JSDOM doesn't provide +if (typeof window !== 'undefined') { + // If XMLSerializer isn't available in the JSDOM environment, mock it + if (!window.XMLSerializer) { + window.XMLSerializer = class XMLSerializer { + serializeToString(node: Node): string { + return `${node.nodeName}`; + } + }; + } + + // If DOMParser isn't available in the JSDOM environment, mock it + if (!window.DOMParser) { + window.DOMParser = class DOMParser { + parseFromString(xmlString: string, mimeType: string): Document { + const document = window.document.implementation.createDocument(null, 'root', null); + + // Create a basic document structure for testing + const mockElement = document.createElement('mockElement'); + mockElement.textContent = xmlString; + document.documentElement.appendChild(mockElement); + + return document; + } + }; + } +} + +// Silence console errors during tests to keep output clean +jest.spyOn(console, 'error').mockImplementation(() => {}); + +// Reset all mocks after each test +afterEach(() => { + jest.clearAllMocks(); +}); \ No newline at end of file diff --git a/test/utils/testConfig.js b/test/utils/testConfig.ts similarity index 100% rename from test/utils/testConfig.js rename to test/utils/testConfig.ts From 81869a2b4ed5ff7e0e55b20dbf3814fce7ad6993 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 21:01:45 -0500 Subject: [PATCH 19/38] fix to remove errant http://www.w3.org/1999/xhtml on root elements during serialization --- src/core/JSONToXML.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/JSONToXML.ts b/src/core/JSONToXML.ts index 512dabe..7a34ca9 100644 --- a/src/core/JSONToXML.ts +++ b/src/core/JSONToXML.ts @@ -43,6 +43,10 @@ export class JSONToXML { // Add XML declaration if specified let xmlString = DOMAdapter.serializeToString(doc); + + // remove xhtml decl inserted by dom + xmlString = xmlString.replace(' xmlns="http://www.w3.org/1999/xhtml"', ''); + if (this.config.outputOptions.xml.declaration) { xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString); } From 0e6e2fc46f69a9b5e2775bede7cd079b43e28537 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 21:06:54 -0500 Subject: [PATCH 20/38] rearranged tests added a testUtils package with normalize --- test/{ => unit}/XJX.test.ts | 6 +- test/{ => unit}/core/DOMAdapter.test.ts | 6 +- test/{ => unit}/core/JSONToXML.test.ts | 10 +- test/{ => unit}/core/XMLToJSON.test.ts | 6 +- test/{ => unit}/core/utils/JSONUtil.test.ts | 6 +- test/{ => unit}/core/utils/XMLUtil.test.ts | 8 +- test/utils/testUtils.js | 130 ++++++++++++++++++++ 7 files changed, 151 insertions(+), 21 deletions(-) rename test/{ => unit}/XJX.test.ts (97%) rename test/{ => unit}/core/DOMAdapter.test.ts (96%) rename test/{ => unit}/core/JSONToXML.test.ts (96%) rename test/{ => unit}/core/XMLToJSON.test.ts (97%) rename test/{ => unit}/core/utils/JSONUtil.test.ts (97%) rename test/{ => unit}/core/utils/XMLUtil.test.ts (95%) create mode 100644 test/utils/testUtils.js diff --git a/test/XJX.test.ts b/test/unit/XJX.test.ts similarity index 97% rename from test/XJX.test.ts rename to test/unit/XJX.test.ts index dc75643..d48ecbe 100644 --- a/test/XJX.test.ts +++ b/test/unit/XJX.test.ts @@ -1,9 +1,9 @@ /** * XJX library tests */ -import { XJX } from '../src/XJX'; -import { Configuration } from '../src/core/types/types'; -import { createTestConfig, cloneConfig } from './utils/testConfig'; +import { XJX } from '../../src/XJX'; +import { Configuration } from '../../src/core/types/types'; +import { createTestConfig, cloneConfig } from '../utils/testConfig'; describe('XJX', () => { let xjx: XJX; diff --git a/test/core/DOMAdapter.test.ts b/test/unit/core/DOMAdapter.test.ts similarity index 96% rename from test/core/DOMAdapter.test.ts rename to test/unit/core/DOMAdapter.test.ts index 630367a..f22b3d0 100644 --- a/test/core/DOMAdapter.test.ts +++ b/test/unit/core/DOMAdapter.test.ts @@ -1,9 +1,9 @@ /** * Tests for DOMAdapter */ -import { DOMAdapter } from '../../src/core/DOMAdapter'; -import { XMLToJSONError } from '../../src/core/types/errors'; -import { createTestConfig } from '../utils/testConfig'; +import { DOMAdapter } from '../../../src/core/DOMAdapter'; +import { XMLToJSONError } from '../../../src/core/types/errors'; +import { createTestConfig } from '../../utils/testConfig'; describe('DOMAdapter', () => { // We don't directly pass the config to DOMAdapter, diff --git a/test/core/JSONToXML.test.ts b/test/unit/core/JSONToXML.test.ts similarity index 96% rename from test/core/JSONToXML.test.ts rename to test/unit/core/JSONToXML.test.ts index 3857a6f..648d718 100644 --- a/test/core/JSONToXML.test.ts +++ b/test/unit/core/JSONToXML.test.ts @@ -1,11 +1,11 @@ /** * Tests for JSONToXML class */ -import { JSONToXML } from '../../src/core/JSONToXML'; -import { XMLToJSON } from '../../src/core/XMLToJSON'; -import { Configuration } from '../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../utils/testConfig'; -import { DOMAdapter } from '../../src/core/DOMAdapter'; +import { JSONToXML } from '../../../src/core/JSONToXML'; +import { XMLToJSON } from '../../../src/core/XMLToJSON'; +import { Configuration } from '../../../src/core/types/types'; +import { createTestConfig, cloneConfig } from '../../utils/testConfig'; +import { DOMAdapter } from '../../../src/core/DOMAdapter'; describe('JSONToXML', () => { let jsonToXML: JSONToXML; diff --git a/test/core/XMLToJSON.test.ts b/test/unit/core/XMLToJSON.test.ts similarity index 97% rename from test/core/XMLToJSON.test.ts rename to test/unit/core/XMLToJSON.test.ts index e320c65..c115fbd 100644 --- a/test/core/XMLToJSON.test.ts +++ b/test/unit/core/XMLToJSON.test.ts @@ -1,9 +1,9 @@ /** * Tests for XMLToJSON class */ -import { XMLToJSON } from '../../src/core/XMLToJSON'; -import { Configuration } from '../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../utils/testConfig'; +import { XMLToJSON } from '../../../src/core/XMLToJSON'; +import { Configuration } from '../../../src/core/types/types'; +import { createTestConfig, cloneConfig } from '../../utils/testConfig'; describe('XMLToJSON', () => { let xmlToJSON: XMLToJSON; diff --git a/test/core/utils/JSONUtil.test.ts b/test/unit/core/utils/JSONUtil.test.ts similarity index 97% rename from test/core/utils/JSONUtil.test.ts rename to test/unit/core/utils/JSONUtil.test.ts index 6cafdeb..e6821f6 100644 --- a/test/core/utils/JSONUtil.test.ts +++ b/test/unit/core/utils/JSONUtil.test.ts @@ -1,9 +1,9 @@ /** * Tests for JSONUtil class */ -import { JSONUtil } from '../../../src/core/utils/JSONUtil'; -import { Configuration } from '../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../utils/testConfig'; +import { JSONUtil } from '../../../../src/core/utils/JSONUtil'; +import { Configuration } from '../../../../src/core/types/types'; +import { createTestConfig, cloneConfig } from '../../../utils/testConfig'; describe('JSONUtil', () => { let jsonUtil: JSONUtil; diff --git a/test/core/utils/XMLUtil.test.ts b/test/unit/core/utils/XMLUtil.test.ts similarity index 95% rename from test/core/utils/XMLUtil.test.ts rename to test/unit/core/utils/XMLUtil.test.ts index 0ead2fb..670a75e 100644 --- a/test/core/utils/XMLUtil.test.ts +++ b/test/unit/core/utils/XMLUtil.test.ts @@ -1,10 +1,10 @@ /** * Tests for XMLUtil class */ -import { XMLUtil } from '../../../src/core/utils/XMLUtil'; -import { DOMAdapter } from '../../../src/core/DOMAdapter'; -import { Configuration } from '../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../utils/testConfig'; +import { XMLUtil } from '../../../../src/core/utils/XMLUtil'; +import { DOMAdapter } from '../../../../src/core/DOMAdapter'; +import { Configuration } from '../../../../src/core/types/types'; +import { createTestConfig, cloneConfig } from '../../../utils/testConfig'; describe('XMLUtil', () => { let xmlUtil: XMLUtil; diff --git a/test/utils/testUtils.js b/test/utils/testUtils.js new file mode 100644 index 0000000..0e94912 --- /dev/null +++ b/test/utils/testUtils.js @@ -0,0 +1,130 @@ +import path from 'path'; +import fs from 'fs'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + + +/** + * Load test fixture file + * @param {string} type - Type of fixture (xml|json) + * @param {string} name - Name of the fixture file without extension + * @returns {string|Object} - File contents as string (XML) or parsed object (JSON) + */ +export function loadFixture(type, name) { + const fixturePath = path.resolve(__dirname, '..', 'fixtures', type, `${name}.${type}`); + + try { + const content = fs.readFileSync(fixturePath, 'utf8'); + + // Parse JSON fixtures, return XML as string + if (type === 'json') { + return JSON.parse(content); + } + + return content; + } catch (error) { + throw new Error(`Error loading fixture ${fixturePath}: ${error.message}`); + } +} + +/** + * Create a complete configuration for testing + * @param {Object} overrides - Configuration overrides + * @returns {Object} - Complete configuration object + */ +export function createTestConfig(overrides = {}) { + // Base test configuration with all options specified + const baseConfig = { + // Features to preserve during transformation + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveWhitespace: false, + + // value transforms + valueTransforms: [], + + // Output options + outputOptions: { + prettyPrint: false, + indent: 3, + compact: false, + removeEmptyValueNodes: false, + + // JSON-specific options + json: { + }, + + // XML-specific options + xml: { + declaration: true, + }, + }, + + // Property names in the JSON representation + propNames: { + namespace: "@ns", + prefix: "@prefix", + attributes: "@attrs", + value: "@val", + cdata: "@cdata", + comments: "@comments", + processing: "@processing", + children: "@children", + }, + }; + + // Deep merge with overrides + return deepMerge(baseConfig, overrides); +} + +/** + * Deep merge two objects + * @param {Object} target - Target object + * @param {Object} source - Source object + * @returns {Object} - Merged object + */ +function deepMerge(target, source) { + const output = { ...target }; + + if (isObject(target) && isObject(source)) { + Object.keys(source).forEach(key => { + if (isObject(source[key])) { + if (!(key in target)) { + Object.assign(output, { [key]: source[key] }); + } else { + output[key] = deepMerge(target[key], source[key]); + } + } else { + Object.assign(output, { [key]: source[key] }); + } + }); + } + + return output; +} + +/** + * Check if value is an object + * @param {any} item - Value to check + * @returns {boolean} - Whether value is an object + */ +function isObject(item) { + return item && typeof item === 'object' && !Array.isArray(item); +} + +/** + * Normalize XML string by removing whitespace between tags + * @param {string} xml - XML string + * @returns {string} - Normalized XML string + */ +export function normalizeXML(xml) { + return xml + .replace(/>\s+<') // Remove whitespace between tags + .replace(/\s+/g, ' ') // Normalize whitespace + .trim(); // Trim leading/trailing whitespace +} \ No newline at end of file From 18e15ba9bfb677fbacb1388a44368c0a6ccee1d6 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 21:12:46 -0500 Subject: [PATCH 21/38] add deepmerge for configuration to support partial deep config overrides --- src/XJX.ts | 22 +++++++--- src/core/utils/JSONUtil.ts | 70 ++++++++++++++++++++----------- test/utils/testUtils.js | 86 -------------------------------------- 3 files changed, 62 insertions(+), 116 deletions(-) diff --git a/src/XJX.ts b/src/XJX.ts index 96fb111..013f574 100644 --- a/src/XJX.ts +++ b/src/XJX.ts @@ -21,10 +21,19 @@ export class XJX { * @param config Configuration options */ constructor(config: Partial = {}) { - this.config = { ...DEFAULT_CONFIG, ...config }; - - // Initialize all components with config + // First create a jsonUtil instance with default config to use its methods + this.jsonUtil = new JSONUtil(DEFAULT_CONFIG); + + // Create a deep clone of the default config + const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG); + + // Deep merge with the provided config + this.config = this.jsonUtil.deepMerge(defaultClone, config); + + // Re-initialize jsonUtil with the merged config this.jsonUtil = new JSONUtil(this.config); + + // Initialize other components this.xmlUtil = new XMLUtil(this.config); this.xmltojson = new XMLToJSON(this.config); this.jsontoxml = new JSONToXML(this.config); @@ -77,7 +86,10 @@ export class XJX { * @param xmlString XML string to validate * @returns Validation result */ - public validateXML(xmlString: string): { isValid: boolean; message?: string } { + public validateXML(xmlString: string): { + isValid: boolean; + message?: string; + } { return this.xmlUtil.validateXML(xmlString); } @@ -87,4 +99,4 @@ export class XJX { public cleanup(): void { DOMAdapter.cleanup(); } -} \ No newline at end of file +} diff --git a/src/core/utils/JSONUtil.ts b/src/core/utils/JSONUtil.ts index 95b5ded..c11a5ea 100644 --- a/src/core/utils/JSONUtil.ts +++ b/src/core/utils/JSONUtil.ts @@ -71,18 +71,21 @@ export class JSONUtil { } // Check if this is a special property name that matches the config - if (segment === this.config.propNames.value || - segment === this.config.propNames.children || - segment === this.config.propNames.attributes || - segment === this.config.propNames.namespace || - segment === this.config.propNames.prefix || - segment === this.config.propNames.cdata || - segment === this.config.propNames.comments || - segment === this.config.propNames.instruction || - segment === this.config.propNames.target) { - const configKey = Object.entries(this.config.propNames) - .find(([_, value]) => value === segment)?.[0]; - + if ( + segment === this.config.propNames.value || + segment === this.config.propNames.children || + segment === this.config.propNames.attributes || + segment === this.config.propNames.namespace || + segment === this.config.propNames.prefix || + segment === this.config.propNames.cdata || + segment === this.config.propNames.comments || + segment === this.config.propNames.instruction || + segment === this.config.propNames.target + ) { + const configKey = Object.entries(this.config.propNames).find( + ([_, value]) => value === segment + )?.[0]; + if (configKey && obj[segment] !== undefined) { return obj[segment]; } @@ -205,7 +208,7 @@ export class JSONUtil { isEmpty(value: any): boolean { if (value == null) return true; if (Array.isArray(value)) return value.length === 0; - if (typeof value === 'object') return Object.keys(value).length === 0; + if (typeof value === "object") return Object.keys(value).length === 0; return false; } @@ -219,7 +222,7 @@ export class JSONUtil { try { return JSON.stringify(obj, null, indent); } catch (error) { - return '[Cannot stringify object]'; + return "[Cannot stringify object]"; } } @@ -232,33 +235,50 @@ export class JSONUtil { try { return JSON.parse(JSON.stringify(obj)); } catch (error) { - throw new Error(`Failed to deep clone object: ${error instanceof Error ? error.message : String(error)}`); + throw new Error( + `Failed to deep clone object: ${ + error instanceof Error ? error.message : String(error) + }` + ); } } /** - * Deep merge two objects + * Deep merge two objects with proper type handling * @param target Target object * @param source Source object * @returns Merged object (target is modified) */ - deepMerge(target: any, source: any): any { - if (typeof source !== 'object' || source === null) { + deepMerge(target: T, source: Partial): T { + if (!source || typeof source !== "object" || source === null) { return target; } - if (typeof target !== 'object' || target === null) { - return this.deepClone(source); + if (!target || typeof target !== "object" || target === null) { + return source as unknown as T; } - Object.keys(source).forEach(key => { - if (source[key] instanceof Object && key in target && target[key] instanceof Object) { - this.deepMerge(target[key], source[key]); + Object.keys(source).forEach((key) => { + const sourceValue = source[key as keyof Partial]; + const targetValue = target[key as keyof T]; + + // If both source and target values are objects, recursively merge them + if ( + sourceValue !== null && + targetValue !== null && + typeof sourceValue === "object" && + typeof targetValue === "object" && + !Array.isArray(sourceValue) && + !Array.isArray(targetValue) + ) { + // Recursively merge the nested objects + (target as any)[key] = this.deepMerge(targetValue, sourceValue as any); } else { - target[key] = this.deepClone(source[key]); + // Otherwise just replace the value + (target as any)[key] = sourceValue; } }); return target; } -} \ No newline at end of file +} diff --git a/test/utils/testUtils.js b/test/utils/testUtils.js index 0e94912..c178197 100644 --- a/test/utils/testUtils.js +++ b/test/utils/testUtils.js @@ -29,93 +29,7 @@ export function loadFixture(type, name) { } } -/** - * Create a complete configuration for testing - * @param {Object} overrides - Configuration overrides - * @returns {Object} - Complete configuration object - */ -export function createTestConfig(overrides = {}) { - // Base test configuration with all options specified - const baseConfig = { - // Features to preserve during transformation - preserveNamespaces: true, - preserveComments: true, - preserveProcessingInstr: true, - preserveCDATA: true, - preserveTextNodes: true, - preserveWhitespace: false, - - // value transforms - valueTransforms: [], - - // Output options - outputOptions: { - prettyPrint: false, - indent: 3, - compact: false, - removeEmptyValueNodes: false, - - // JSON-specific options - json: { - }, - - // XML-specific options - xml: { - declaration: true, - }, - }, - - // Property names in the JSON representation - propNames: { - namespace: "@ns", - prefix: "@prefix", - attributes: "@attrs", - value: "@val", - cdata: "@cdata", - comments: "@comments", - processing: "@processing", - children: "@children", - }, - }; - - // Deep merge with overrides - return deepMerge(baseConfig, overrides); -} -/** - * Deep merge two objects - * @param {Object} target - Target object - * @param {Object} source - Source object - * @returns {Object} - Merged object - */ -function deepMerge(target, source) { - const output = { ...target }; - - if (isObject(target) && isObject(source)) { - Object.keys(source).forEach(key => { - if (isObject(source[key])) { - if (!(key in target)) { - Object.assign(output, { [key]: source[key] }); - } else { - output[key] = deepMerge(target[key], source[key]); - } - } else { - Object.assign(output, { [key]: source[key] }); - } - }); - } - - return output; -} - -/** - * Check if value is an object - * @param {any} item - Value to check - * @returns {boolean} - Whether value is an object - */ -function isObject(item) { - return item && typeof item === 'object' && !Array.isArray(item); -} /** * Normalize XML string by removing whitespace between tags From 1c1974882371f299747f3d14ab141254cf589d11 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 21:15:27 -0500 Subject: [PATCH 22/38] updated test utils to include normalize --- test/utils/testConfig.ts | 49 ---------------------- test/utils/testUtils.js | 44 -------------------- test/utils/testUtils.ts | 88 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 93 deletions(-) delete mode 100644 test/utils/testConfig.ts delete mode 100644 test/utils/testUtils.js create mode 100644 test/utils/testUtils.ts diff --git a/test/utils/testConfig.ts b/test/utils/testConfig.ts deleted file mode 100644 index 844e6e6..0000000 --- a/test/utils/testConfig.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Standard test configuration for XJX library tests - */ -import { Configuration } from '../../src/core/types/types'; - -/** - * Creates a standard test configuration to use across all tests - * This ensures tests are not affected by changes to the default configuration - */ -export const createTestConfig = (): Configuration => { - return { - preserveNamespaces: true, - preserveComments: true, - preserveProcessingInstr: true, - preserveCDATA: true, - preserveTextNodes: true, - preserveWhitespace: false, - preserveAttributes: true, - - outputOptions: { - prettyPrint: true, - indent: 2, - compact: true, - json: {}, - xml: { - declaration: true, - }, - }, - - propNames: { - namespace: "$ns", - prefix: "$pre", - attributes: "$attr", - value: "$val", - cdata: "$cdata", - comments: "$cmnt", - instruction: "$pi", - target: "$trgt", - children: "$children", - }, - }; -}; - -/** - * Deep clone an object - useful for ensuring test isolation - */ -export const cloneConfig = (config: Configuration): Configuration => { - return JSON.parse(JSON.stringify(config)); -}; \ No newline at end of file diff --git a/test/utils/testUtils.js b/test/utils/testUtils.js deleted file mode 100644 index c178197..0000000 --- a/test/utils/testUtils.js +++ /dev/null @@ -1,44 +0,0 @@ -import path from 'path'; -import fs from 'fs'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - - -/** - * Load test fixture file - * @param {string} type - Type of fixture (xml|json) - * @param {string} name - Name of the fixture file without extension - * @returns {string|Object} - File contents as string (XML) or parsed object (JSON) - */ -export function loadFixture(type, name) { - const fixturePath = path.resolve(__dirname, '..', 'fixtures', type, `${name}.${type}`); - - try { - const content = fs.readFileSync(fixturePath, 'utf8'); - - // Parse JSON fixtures, return XML as string - if (type === 'json') { - return JSON.parse(content); - } - - return content; - } catch (error) { - throw new Error(`Error loading fixture ${fixturePath}: ${error.message}`); - } -} - - - -/** - * Normalize XML string by removing whitespace between tags - * @param {string} xml - XML string - * @returns {string} - Normalized XML string - */ -export function normalizeXML(xml) { - return xml - .replace(/>\s+<') // Remove whitespace between tags - .replace(/\s+/g, ' ') // Normalize whitespace - .trim(); // Trim leading/trailing whitespace -} \ No newline at end of file diff --git a/test/utils/testUtils.ts b/test/utils/testUtils.ts new file mode 100644 index 0000000..ebeafb4 --- /dev/null +++ b/test/utils/testUtils.ts @@ -0,0 +1,88 @@ +import path from 'path'; +import fs from 'fs'; +import { fileURLToPath } from 'url'; +import { Configuration } from '../src/core/types/types'; + +// Get directory information for ES modules +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +/** + * Creates a standard test configuration to use across all tests + * This ensures tests are not affected by changes to the default configuration + */ +export const createTestConfig = (): Configuration => { + return { + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveWhitespace: false, + preserveAttributes: true, + + outputOptions: { + prettyPrint: true, + indent: 2, + compact: true, + json: {}, + xml: { + declaration: true, + }, + }, + + propNames: { + namespace: "$ns", + prefix: "$pre", + attributes: "$attr", + value: "$val", + cdata: "$cdata", + comments: "$cmnt", + instruction: "$pi", + target: "$trgt", + children: "$children", + }, + }; +}; + +/** + * Deep clone an object - useful for ensuring test isolation + */ +export const cloneConfig = (config: Configuration): Configuration => { + return JSON.parse(JSON.stringify(config)); +}; + +/** + * Load test fixture file + * @param type - Type of fixture (xml|json) + * @param name - Name of the fixture file without extension + * @returns File contents as string (XML) or parsed object (JSON) + */ +export function loadFixture(type: 'xml' | 'json', name: string): string | Record { + const fixturePath = path.resolve(__dirname, '..', 'fixtures', type, `${name}.${type}`); + + try { + const content = fs.readFileSync(fixturePath, 'utf8'); + + // Parse JSON fixtures, return XML as string + if (type === 'json') { + return JSON.parse(content); + } + + return content; + } catch (error) { + throw new Error(`Error loading fixture ${fixturePath}: ${error instanceof Error ? error.message : String(error)}`); + } +} + +/** + * Normalize XML string by removing whitespace between tags + * @param xml - XML string + * @returns Normalized XML string + */ +export function normalizeXML(xml: string): string { + return xml + .replace(/>\s+<') // Remove whitespace between tags + .replace(/\s+/g, ' ') // Normalize whitespace + .trim(); // Trim leading/trailing whitespace +} \ No newline at end of file From a072c21e469246fe48e4861e5efd13754c1a91a6 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 21:20:56 -0500 Subject: [PATCH 23/38] test tuility updates --- test/unit/core/DOMAdapter.test.ts | 2 +- test/unit/core/JSONToXML.test.ts | 2 +- test/unit/core/XMLToJSON.test.ts | 2 +- test/unit/core/utils/JSONUtil.test.ts | 7 ++++--- test/unit/core/utils/XMLUtil.test.ts | 2 +- test/utils/testUtils.ts | 11 +++++------ 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/test/unit/core/DOMAdapter.test.ts b/test/unit/core/DOMAdapter.test.ts index f22b3d0..2e1fd25 100644 --- a/test/unit/core/DOMAdapter.test.ts +++ b/test/unit/core/DOMAdapter.test.ts @@ -3,7 +3,7 @@ */ import { DOMAdapter } from '../../../src/core/DOMAdapter'; import { XMLToJSONError } from '../../../src/core/types/errors'; -import { createTestConfig } from '../../utils/testConfig'; +import { createTestConfig } from '../../utils/testUtils'; describe('DOMAdapter', () => { // We don't directly pass the config to DOMAdapter, diff --git a/test/unit/core/JSONToXML.test.ts b/test/unit/core/JSONToXML.test.ts index 648d718..f79ca96 100644 --- a/test/unit/core/JSONToXML.test.ts +++ b/test/unit/core/JSONToXML.test.ts @@ -4,7 +4,7 @@ import { JSONToXML } from '../../../src/core/JSONToXML'; import { XMLToJSON } from '../../../src/core/XMLToJSON'; import { Configuration } from '../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../utils/testConfig'; +import { createTestConfig, cloneConfig } from '../../utils/testUtils'; import { DOMAdapter } from '../../../src/core/DOMAdapter'; describe('JSONToXML', () => { diff --git a/test/unit/core/XMLToJSON.test.ts b/test/unit/core/XMLToJSON.test.ts index c115fbd..c679fd1 100644 --- a/test/unit/core/XMLToJSON.test.ts +++ b/test/unit/core/XMLToJSON.test.ts @@ -3,7 +3,7 @@ */ import { XMLToJSON } from '../../../src/core/XMLToJSON'; import { Configuration } from '../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../utils/testConfig'; +import { createTestConfig, cloneConfig } from '../../utils/testUtils'; describe('XMLToJSON', () => { let xmlToJSON: XMLToJSON; diff --git a/test/unit/core/utils/JSONUtil.test.ts b/test/unit/core/utils/JSONUtil.test.ts index e6821f6..5da4422 100644 --- a/test/unit/core/utils/JSONUtil.test.ts +++ b/test/unit/core/utils/JSONUtil.test.ts @@ -3,7 +3,7 @@ */ import { JSONUtil } from '../../../../src/core/utils/JSONUtil'; import { Configuration } from '../../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../../utils/testConfig'; +import { createTestConfig, cloneConfig } from '../../../utils/testUtils'; describe('JSONUtil', () => { let jsonUtil: JSONUtil; @@ -252,8 +252,9 @@ describe('JSONUtil', () => { }); it('should handle null and undefined values', () => { - expect(jsonUtil.deepMerge({ name: "John" }, null)).toEqual({ name: "John" }); - expect(jsonUtil.deepMerge(null, { name: "John" })).toEqual({ name: "John" }); + // Fix: Use an empty object instead of null to match TypeScript constraints + expect(jsonUtil.deepMerge({ name: "John" }, {} as Partial<{name: string}>)).toEqual({ name: "John" }); + expect(jsonUtil.deepMerge({} as {name: string}, { name: "John" })).toEqual({ name: "John" }); }); }); }); \ No newline at end of file diff --git a/test/unit/core/utils/XMLUtil.test.ts b/test/unit/core/utils/XMLUtil.test.ts index 670a75e..f009e24 100644 --- a/test/unit/core/utils/XMLUtil.test.ts +++ b/test/unit/core/utils/XMLUtil.test.ts @@ -4,7 +4,7 @@ import { XMLUtil } from '../../../../src/core/utils/XMLUtil'; import { DOMAdapter } from '../../../../src/core/DOMAdapter'; import { Configuration } from '../../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../../utils/testConfig'; +import { createTestConfig, cloneConfig } from '../../../utils/testUtils'; describe('XMLUtil', () => { let xmlUtil: XMLUtil; diff --git a/test/utils/testUtils.ts b/test/utils/testUtils.ts index ebeafb4..2e767e1 100644 --- a/test/utils/testUtils.ts +++ b/test/utils/testUtils.ts @@ -1,11 +1,9 @@ +/** + * Combined test utilities for the XJX library + */ import path from 'path'; import fs from 'fs'; -import { fileURLToPath } from 'url'; -import { Configuration } from '../src/core/types/types'; - -// Get directory information for ES modules -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +import { Configuration } from '../../src/core/types/types'; /** * Creates a standard test configuration to use across all tests @@ -59,6 +57,7 @@ export const cloneConfig = (config: Configuration): Configuration => { * @returns File contents as string (XML) or parsed object (JSON) */ export function loadFixture(type: 'xml' | 'json', name: string): string | Record { + // Fixed path resolution that doesn't rely on import.meta const fixturePath = path.resolve(__dirname, '..', 'fixtures', type, `${name}.${type}`); try { From 69d597900a0d74cc91e2b5224e7f7a5efd26fa82 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 21:29:24 -0500 Subject: [PATCH 24/38] updated xm comparisons to use normalized strings --- test/unit/XJX.test.ts | 42 ++++++++++++++++++++++++---- test/unit/core/DOMAdapter.test.ts | 6 ++-- test/unit/core/JSONToXML.test.ts | 26 ++++++++--------- test/unit/core/XMLToJSON.test.ts | 26 ++++++++--------- test/unit/core/utils/XMLUtil.test.ts | 6 ++-- 5 files changed, 69 insertions(+), 37 deletions(-) diff --git a/test/unit/XJX.test.ts b/test/unit/XJX.test.ts index d48ecbe..f720918 100644 --- a/test/unit/XJX.test.ts +++ b/test/unit/XJX.test.ts @@ -3,7 +3,7 @@ */ import { XJX } from '../../src/XJX'; import { Configuration } from '../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../utils/testConfig'; +import { createTestConfig, cloneConfig, normalizeXML } from '../utils/testUtils'; describe('XJX', () => { let xjx: XJX; @@ -96,7 +96,7 @@ describe('XJX', () => { } }; - const result = xjx.jsonToXml(json); + const result = normalizeXML(xjx.jsonToXml(json)); expect(result).toContain(''); expect(result).toContain('Test'); expect(result).toContain(''); @@ -104,7 +104,7 @@ describe('XJX', () => { it('should include XML declaration when enabled', () => { const json = { root: { $val: 'Test' } }; - const result = xjx.jsonToXml(json); + const result = normalizeXML(xjx.jsonToXml(json)); expect(result).toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); }); @@ -125,7 +125,7 @@ describe('XJX', () => { } }; - const result = xjx.jsonToXml(json); + const result = normalizeXML(xjx.jsonToXml(json)); expect(result).toContain('Test'); }); @@ -136,7 +136,7 @@ describe('XJX', () => { const customXjx = new XJX(customConfig); const json = { root: { $val: 'Test' } }; - const result = customXjx.jsonToXml(json); + const result = normalizeXML(customXjx.jsonToXml(json)); expect(result).not.toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); @@ -205,6 +205,38 @@ describe('XJX', () => { }); }); + describe('round-trip XML conversion', () => { + it('should preserve XML content in round-trip conversion', () => { + const originalXml = ` + + + The Great Gatsby + F. Scott Fitzgerald + 1925 + + that should be preserved]]> + + + `; + + // Convert to JSON and back to XML + const json = xjx.xmlToJson(originalXml); + const resultXml = xjx.jsonToXml(json); + + // Normalize both the original and the result to compare + const normalizedOriginal = normalizeXML(originalXml); + const normalizedResult = normalizeXML(resultXml); + + // Check for key elements + expect(normalizedResult).toContain(''); + expect(normalizedResult).toContain('The Great Gatsby'); + expect(normalizedResult).toContain('F. Scott Fitzgerald'); + expect(normalizedResult).toContain('1925'); + expect(normalizedResult).toContain(''); + expect(normalizedResult).toContain(' that should be preserved]]>'); + }); + }); + describe('configuration with custom property names', () => { it('should work with custom property names for XML tokens', () => { // Create special instance for this test with custom property names diff --git a/test/unit/core/DOMAdapter.test.ts b/test/unit/core/DOMAdapter.test.ts index 2e1fd25..2de12a8 100644 --- a/test/unit/core/DOMAdapter.test.ts +++ b/test/unit/core/DOMAdapter.test.ts @@ -3,7 +3,7 @@ */ import { DOMAdapter } from '../../../src/core/DOMAdapter'; import { XMLToJSONError } from '../../../src/core/types/errors'; -import { createTestConfig } from '../../utils/testUtils'; +import { createTestConfig, normalizeXML } from '../../utils/testUtils'; describe('DOMAdapter', () => { // We don't directly pass the config to DOMAdapter, @@ -29,7 +29,7 @@ describe('DOMAdapter', () => { }); it('should parse XML strings', () => { - const xml = 'Test'; + const xml = normalizeXML('Test'); const doc = DOMAdapter.parseFromString(xml); expect(doc.documentElement.nodeName).toBe('root'); @@ -39,7 +39,7 @@ describe('DOMAdapter', () => { it('should serialize DOM nodes to XML strings', () => { const xml = 'Test'; const doc = DOMAdapter.parseFromString(xml); - const serialized = DOMAdapter.serializeToString(doc); + const serialized = normalizeXML(DOMAdapter.serializeToString(doc)); // JSDOM serialization may add XML declaration and namespace expect(serialized).toContain(''); diff --git a/test/unit/core/JSONToXML.test.ts b/test/unit/core/JSONToXML.test.ts index f79ca96..e752cd5 100644 --- a/test/unit/core/JSONToXML.test.ts +++ b/test/unit/core/JSONToXML.test.ts @@ -4,7 +4,7 @@ import { JSONToXML } from '../../../src/core/JSONToXML'; import { XMLToJSON } from '../../../src/core/XMLToJSON'; import { Configuration } from '../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../utils/testUtils'; +import { createTestConfig, cloneConfig, normalizeXML } from '../../utils/testUtils'; import { DOMAdapter } from '../../../src/core/DOMAdapter'; describe('JSONToXML', () => { @@ -37,7 +37,7 @@ describe('JSONToXML', () => { } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toContain(''); expect(result).toContain('Test'); @@ -46,7 +46,7 @@ describe('JSONToXML', () => { it('should include XML declaration when enabled', () => { const json = { root: { [testConfig.propNames.value]: 'Test' } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); }); @@ -67,7 +67,7 @@ describe('JSONToXML', () => { } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toContain('Test'); }); @@ -87,7 +87,7 @@ describe('JSONToXML', () => { } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toContain('xmlns="http://example.org"'); expect(result).toContain(' { } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toContain('bold text]]>'); }); @@ -127,7 +127,7 @@ describe('JSONToXML', () => { } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toContain(''); }); @@ -151,7 +151,7 @@ describe('JSONToXML', () => { } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toContain(''); }); @@ -175,7 +175,7 @@ describe('JSONToXML', () => { } }; - const result = jsonToXML.serialize(json); + const result = normalizeXML(jsonToXML.serialize(json)); expect(result).toContain(''); expect(result).toContain('Child Text'); @@ -197,7 +197,7 @@ describe('JSONToXML', () => { // XML -> JSON -> XML round trip const json = xmlToJSON.parse(originalXml); - const resultXml = jsonToXML.serialize(json); + const resultXml = normalizeXML(jsonToXML.serialize(json)); // The resulting XML should have the same structure and content expect(resultXml).toContain(''); @@ -217,7 +217,7 @@ describe('JSONToXML', () => { const customJsonToXML = new JSONToXML(customConfig); const json = { root: { [testConfig.propNames.value]: 'Test' } }; - const result = customJsonToXML.serialize(json); + const result = normalizeXML(customJsonToXML.serialize(json)); expect(result).not.toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/); }); @@ -272,7 +272,7 @@ describe('JSONToXML', () => { } }; - const result = customJsonToXML.serialize(json); + const result = normalizeXML(customJsonToXML.serialize(json)); // Namespaces should be ignored expect(result).not.toContain('xmlns="http://example.org"'); @@ -311,7 +311,7 @@ describe('JSONToXML', () => { } }; - const result = customJsonToXML.serialize(json); + const result = normalizeXML(customJsonToXML.serialize(json)); expect(result).toContain('Test'); }); diff --git a/test/unit/core/XMLToJSON.test.ts b/test/unit/core/XMLToJSON.test.ts index c679fd1..453f4eb 100644 --- a/test/unit/core/XMLToJSON.test.ts +++ b/test/unit/core/XMLToJSON.test.ts @@ -3,7 +3,7 @@ */ import { XMLToJSON } from '../../../src/core/XMLToJSON'; import { Configuration } from '../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../utils/testUtils'; +import { createTestConfig, cloneConfig, normalizeXML } from '../../utils/testUtils'; describe('XMLToJSON', () => { let xmlToJSON: XMLToJSON; @@ -16,7 +16,7 @@ describe('XMLToJSON', () => { describe('parse', () => { it('should convert a simple XML string to JSON', () => { - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = xmlToJSON.parse(xml); expect(result).toHaveProperty('root'); @@ -26,7 +26,7 @@ describe('XMLToJSON', () => { }); it('should handle XML attributes', () => { - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = xmlToJSON.parse(xml); expect(result.root[testConfig.propNames.children][0].item).toHaveProperty(testConfig.propNames.attributes); @@ -40,7 +40,7 @@ describe('XMLToJSON', () => { }); it('should handle namespaces when enabled', () => { - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = xmlToJSON.parse(xml); expect(result.root).toHaveProperty(testConfig.propNames.namespace); @@ -49,7 +49,7 @@ describe('XMLToJSON', () => { }); it('should handle CDATA sections', () => { - const xml = 'bold text]]>'; + const xml = normalizeXML('bold text]]>'); const result = xmlToJSON.parse(xml); expect(result.root[testConfig.propNames.children][0].item[testConfig.propNames.children][0]).toHaveProperty( @@ -59,7 +59,7 @@ describe('XMLToJSON', () => { }); it('should handle comments when enabled', () => { - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = xmlToJSON.parse(xml); expect(result.root[testConfig.propNames.children][0]).toHaveProperty( @@ -69,7 +69,7 @@ describe('XMLToJSON', () => { }); it('should handle processing instructions when enabled', () => { - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = xmlToJSON.parse(xml); const piElement = result.root[testConfig.propNames.children].find( @@ -82,7 +82,7 @@ describe('XMLToJSON', () => { }); it('should handle nested elements', () => { - const xml = 'Child Text'; + const xml = normalizeXML('Child Text'); const result = xmlToJSON.parse(xml); expect(result.root[testConfig.propNames.children][0].parent[testConfig.propNames.children][0].child) @@ -90,7 +90,7 @@ describe('XMLToJSON', () => { }); it('should handle empty elements', () => { - const xml = ''; + const xml = normalizeXML(''); const result = xmlToJSON.parse(xml); const children = result.root[testConfig.propNames.children]; @@ -108,7 +108,7 @@ describe('XMLToJSON', () => { customConfig.preserveNamespaces = false; const customXmlToJSON = new XMLToJSON(customConfig); - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = customXmlToJSON.parse(xml); expect(result.root).not.toHaveProperty(testConfig.propNames.namespace); @@ -121,7 +121,7 @@ describe('XMLToJSON', () => { customConfig.preserveComments = false; const customXmlToJSON = new XMLToJSON(customConfig); - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = customXmlToJSON.parse(xml); const hasComment = result.root[testConfig.propNames.children].some( @@ -136,7 +136,7 @@ describe('XMLToJSON', () => { customConfig.preserveCDATA = false; const customXmlToJSON = new XMLToJSON(customConfig); - const xml = 'bold text]]>'; + const xml = normalizeXML('bold text]]>'); const result = customXmlToJSON.parse(xml); const hasCDATA = result.root[testConfig.propNames.children][0].item[testConfig.propNames.children]?.some( @@ -162,7 +162,7 @@ describe('XMLToJSON', () => { const customXmlToJSON = new XMLToJSON(customConfig); - const xml = 'Test'; + const xml = normalizeXML('Test'); const result = customXmlToJSON.parse(xml); expect(result.root).toHaveProperty('_children'); diff --git a/test/unit/core/utils/XMLUtil.test.ts b/test/unit/core/utils/XMLUtil.test.ts index f009e24..72872ad 100644 --- a/test/unit/core/utils/XMLUtil.test.ts +++ b/test/unit/core/utils/XMLUtil.test.ts @@ -4,7 +4,7 @@ import { XMLUtil } from '../../../../src/core/utils/XMLUtil'; import { DOMAdapter } from '../../../../src/core/DOMAdapter'; import { Configuration } from '../../../../src/core/types/types'; -import { createTestConfig, cloneConfig } from '../../../utils/testUtils'; +import { createTestConfig, cloneConfig, normalizeXML } from '../../../utils/testUtils'; describe('XMLUtil', () => { let xmlUtil: XMLUtil; @@ -32,14 +32,14 @@ describe('XMLUtil', () => { it('should handle XML with attributes', () => { const xml = 'Test'; - const result = xmlUtil.prettyPrintXml(xml); + const result = normalizeXML(xmlUtil.prettyPrintXml(xml)); expect(result).toContain(''); }); it('should handle empty elements correctly', () => { const xml = ''; - const result = xmlUtil.prettyPrintXml(xml); + const result = normalizeXML(xmlUtil.prettyPrintXml(xml)); expect(result).toContain(''); expect(result).toContain(''); From 2863518c1f5931028377ef1af287f1e9346658c3 Mon Sep 17 00:00:00 2001 From: William Summers Date: Thu, 24 Apr 2025 21:37:03 -0500 Subject: [PATCH 25/38] updated test reporting --- jest.config.js | 10 +++ package-lock.json | 64 ++++++++++++++++++- package.json | 5 +- .../test-report/index.js | 3 + .../test-report/result.js | 1 + reports/test-report.html | 1 + 6 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 reports/jest-html-reporters-attach/test-report/index.js create mode 100644 reports/jest-html-reporters-attach/test-report/result.js create mode 100644 reports/test-report.html diff --git a/jest.config.js b/jest.config.js index c2110db..a7f4e48 100644 --- a/jest.config.js +++ b/jest.config.js @@ -30,6 +30,16 @@ const config = { ], setupFilesAfterEnv: [ '/test/jest.setup.ts' + ], + reporters: [ + 'default', + ['jest-html-reporters', { + publicPath: 'reports/', + filename: 'test-report.html', + expand: false, // expands test case results + includeFailureMsg: true, + includeConsoleLog: true + }] ] }; diff --git a/package-lock.json b/package-lock.json index 0db9e1b..f086295 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "xmltojson", + "name": "xjx", "version": "3.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "xmltojson", + "name": "xjx", "version": "3.0.0", "license": "MIT", "devDependencies": { @@ -22,6 +22,7 @@ "eslint-plugin-prettier": "^4.2.1", "jest": "^29.6.0", "jest-environment-jsdom": "^29.6.0", + "jest-html-reporters": "^3.1.7", "prettier": "^2.8.7", "rimraf": "^4.4.1", "rollup": "^3.29.5", @@ -4250,6 +4251,31 @@ "node": ">= 6" } }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/fs-minipass": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", @@ -5471,6 +5497,17 @@ "fsevents": "^2.3.2" } }, + "node_modules/jest-html-reporters": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/jest-html-reporters/-/jest-html-reporters-3.1.7.tgz", + "integrity": "sha512-GTmjqK6muQ0S0Mnksf9QkL9X9z2FGIpNSxC52E0PHDzjPQ1XDu2+XTI3B3FS43ZiUzD1f354/5FfwbNIBzT7ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^10.0.0", + "open": "^8.0.3" + } + }, "node_modules/jest-leak-detector": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", @@ -5902,6 +5939,29 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", diff --git a/package.json b/package.json index 73a90ca..0f89bcc 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "README.md", "package.json" ], -"scripts": { + "scripts": { "clean": "rimraf dist", "build": "npm run clean && npm run build:types && npm run build:js", "build:types": "tsc --emitDeclarationOnly --outDir dist/dts", @@ -83,6 +83,7 @@ "eslint-plugin-prettier": "^4.2.1", "jest": "^29.6.0", "jest-environment-jsdom": "^29.6.0", + "jest-html-reporters": "^3.1.7", "prettier": "^2.8.7", "rimraf": "^4.4.1", "rollup": "^3.29.5", @@ -107,4 +108,4 @@ "engines": { "node": ">=14.16.0" } -} \ No newline at end of file +} diff --git a/reports/jest-html-reporters-attach/test-report/index.js b/reports/jest-html-reporters-attach/test-report/index.js new file mode 100644 index 0000000..84233b1 --- /dev/null +++ b/reports/jest-html-reporters-attach/test-report/index.js @@ -0,0 +1,3 @@ +/*! For license information please see index.js.LICENSE.txt */ +!function(){var e={9899:function(e){e.exports="./jest-html-reporters-attach/test-report"},5304:function(e,t,n){"use strict";function r(e,t){for(var n=0;n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,c=!0,l=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return c=e.done,e},e:function(e){l=!0,i=e},f:function(){try{c||null==n.return||n.return()}finally{if(l)throw i}}}}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0?40*e+55:0,c=t>0?40*t+55:0,s=n>0?40*n+55:0;r[a]=function(e){var t,n=[],r=o(e);try{for(r.s();!(t=r.n()).done;){var a=t.value;n.push(l(a))}}catch(i){r.e(i)}finally{r.f()}return"#"+n.join("")}([i,c,s])}(t,n,r,e)}))}))})),d(0,23).forEach((function(t){var n=t+232,r=l(10*t+8);e[n]="#"+r+r+r})),e}()};function l(e){for(var t=e.toString(16);t.length<2;)t="0"+t;return t}function s(e,t,n,r){var o;return"text"===t?o=function(e,t){if(t.escapeXML)return i.encodeXML(e);return e}(n,r):"display"===t?o=function(e,t,n){t=parseInt(t,10);var r,o={"-1":function(){return"
"},0:function(){return e.length&&u(e)},1:function(){return p(e,"b")},3:function(){return p(e,"i")},4:function(){return p(e,"u")},8:function(){return h(e,"display:none")},9:function(){return p(e,"strike")},22:function(){return h(e,"font-weight:normal;text-decoration:none;font-style:normal")},23:function(){return g(e,"i")},24:function(){return g(e,"u")},39:function(){return m(e,n.fg)},49:function(){return v(e,n.bg)},53:function(){return h(e,"text-decoration:overline")}};o[t]?r=o[t]():4"})).join("")}function d(e,t){for(var n=[],r=e;r<=t;r++)n.push(r);return n}function f(e){var t=null;return 0===(e=parseInt(e,10))?t="all":1===e?t="bold":2")}function h(e,t){return p(e,"span",t)}function m(e,t){return p(e,"span","color:"+t)}function v(e,t){return p(e,"span","background-color:"+t)}function g(e,t){var n;if(e.slice(-1)[0]===t&&(n=e.pop()),n)return""}var b=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),(t=t||{}).colors&&(t.colors=Object.assign({},c.colors,t.colors)),this.options=Object.assign({},c,t),this.stack=[],this.stickyStack=[]}var t,n,a;return t=e,(n=[{key:"toHtml",value:function(e){var t=this;e="string"===typeof e?[e]:e;var n=this.stack,r=this.options,a=[];return this.stickyStack.forEach((function(e){var t=s(n,e.token,e.data,r);t&&a.push(t)})),function(e,t,n){var r=!1;function a(){return""}function i(e){return t.newline?n("display",-1):n("text",e),""}var c=[{pattern:/^\x08+/,sub:a},{pattern:/^\x1b\[[012]?K/,sub:a},{pattern:/^\x1b\[\(B/,sub:a},{pattern:/^\x1b\[[34]8;2;\d+;\d+;\d+m/,sub:function(e){return n("rgb",e),""}},{pattern:/^\x1b\[38;5;(\d+)m/,sub:function(e,t){return n("xterm256Foreground",t),""}},{pattern:/^\x1b\[48;5;(\d+)m/,sub:function(e,t){return n("xterm256Background",t),""}},{pattern:/^\n/,sub:i},{pattern:/^\r+\n/,sub:i},{pattern:/^\r/,sub:i},{pattern:/^\x1b\[((?:\d{1,3};?)+|)m/,sub:function(e,t){r=!0,0===t.trim().length&&(t="0");var a,i=o(t=t.trimRight(";").split(";"));try{for(i.s();!(a=i.n()).done;){var c=a.value;n("display",c)}}catch(l){i.e(l)}finally{i.f()}return""}},{pattern:/^\x1b\[\d?J/,sub:a},{pattern:/^\x1b\[\d{0,3};\d{0,3}f/,sub:a},{pattern:/^\x1b\[?[\d;]{0,3}/,sub:a},{pattern:/^(([^\x1b\x08\r\n])+)/,sub:function(e){return n("text",e),""}}];function l(t,n){n>3&&r||(r=!1,e=e.replace(t.pattern,t.sub))}var s=[],u=e.length;e:for(;u>0;){for(var d=0,f=0,p=c.length;f0?" ".concat(t[5]):""," {")),n+=e(t),r&&(n+="}"),t[2]&&(n+="}"),t[4]&&(n+="}"),n})).join("")},t.i=function(e,n,r,o,a){"string"===typeof e&&(e=[[null,e,void 0]]);var i={};if(r)for(var c=0;c0?" ".concat(u[5]):""," {").concat(u[1],"}")),u[5]=a),n&&(u[2]?(u[1]="@media ".concat(u[2]," {").concat(u[1],"}"),u[2]=n):u[2]=n),o&&(u[4]?(u[1]="@supports (".concat(u[4],") {").concat(u[1],"}"),u[4]=o):u[4]="".concat(o)),t.push(u))}},t}},6657:function(e){"use strict";e.exports=function(e){var t=e[1],n=e[3];if(!n)return t;if("function"===typeof btoa){var r=btoa(unescape(encodeURIComponent(JSON.stringify(n)))),o="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(r),a="/*# ".concat(o," */");return[t].concat([a]).join("\n")}return[t].join("\n")}},4890:function(e){var t={px:{px:1,cm:96/2.54,mm:96/25.4,in:96,pt:96/72,pc:16},cm:{px:2.54/96,cm:1,mm:.1,in:2.54,pt:2.54/72,pc:2.54/6},mm:{px:25.4/96,cm:10,mm:1,in:25.4,pt:25.4/72,pc:25.4/6},in:{px:1/96,cm:1/2.54,mm:1/25.4,in:1,pt:1/72,pc:1/6},pt:{px:.75,cm:72/2.54,mm:72/25.4,in:72,pt:1,pc:12},pc:{px:6/96,cm:6/2.54,mm:6/25.4,in:6,pt:6/72,pc:1},deg:{deg:1,grad:.9,rad:180/Math.PI,turn:360},grad:{deg:400/360,grad:1,rad:200/Math.PI,turn:400},rad:{deg:Math.PI/180,grad:Math.PI/200,rad:1,turn:2*Math.PI},turn:{deg:1/360,grad:1/400,rad:.5/Math.PI,turn:1},s:{s:1,ms:.001},ms:{s:1e3,ms:1},Hz:{Hz:1,kHz:1e3},kHz:{Hz:.001,kHz:1},dpi:{dpi:1,dpcm:1/2.54,dppx:1/96},dpcm:{dpi:2.54,dpcm:1,dppx:2.54/96},dppx:{dpi:96,dpcm:96/2.54,dppx:1}};e.exports=function(e,n,r,o){if(!t.hasOwnProperty(r))throw new Error("Cannot convert to "+r);if(!t[r].hasOwnProperty(n))throw new Error("Cannot convert from "+n+" to "+r);var a=t[r][n]*e;return!1!==o?(o=Math.pow(10,parseInt(o)||5),Math.round(a*o)/o):a}},7892:function(e){e.exports=function(){"use strict";var e=1e3,t=6e4,n=36e5,r="millisecond",o="second",a="minute",i="hour",c="day",l="week",s="month",u="quarter",d="year",f="date",p="Invalid Date",h=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,m=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,v={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(e){var t=["th","st","nd","rd"],n=e%100;return"["+e+(t[(n-20)%10]||t[n]||t[0])+"]"}},g=function(e,t,n){var r=String(e);return!r||r.length>=t?e:""+Array(t+1-r.length).join(n)+e},b={s:g,z:function(e){var t=-e.utcOffset(),n=Math.abs(t),r=Math.floor(n/60),o=n%60;return(t<=0?"+":"-")+g(r,2,"0")+":"+g(o,2,"0")},m:function e(t,n){if(t.date()1)return e(i[0])}else{var c=t.name;x[c]=t,o=c}return!r&&o&&(y=o),o||!r&&y},E=function(e,t){if(w(e))return e.clone();var n="object"==typeof t?t:{};return n.date=e,n.args=arguments,new k(n)},C=b;C.l=S,C.i=w,C.w=function(e,t){return E(e,{locale:t.$L,utc:t.$u,x:t.$x,$offset:t.$offset})};var k=function(){function v(e){this.$L=S(e.locale,null,!0),this.parse(e)}var g=v.prototype;return g.parse=function(e){this.$d=function(e){var t=e.date,n=e.utc;if(null===t)return new Date(NaN);if(C.u(t))return new Date;if(t instanceof Date)return new Date(t);if("string"==typeof t&&!/Z$/i.test(t)){var r=t.match(h);if(r){var o=r[2]-1||0,a=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],o,r[3]||1,r[4]||0,r[5]||0,r[6]||0,a)):new Date(r[1],o,r[3]||1,r[4]||0,r[5]||0,r[6]||0,a)}}return new Date(t)}(e),this.$x=e.x||{},this.init()},g.init=function(){var e=this.$d;this.$y=e.getFullYear(),this.$M=e.getMonth(),this.$D=e.getDate(),this.$W=e.getDay(),this.$H=e.getHours(),this.$m=e.getMinutes(),this.$s=e.getSeconds(),this.$ms=e.getMilliseconds()},g.$utils=function(){return C},g.isValid=function(){return!(this.$d.toString()===p)},g.isSame=function(e,t){var n=E(e);return this.startOf(t)<=n&&n<=this.endOf(t)},g.isAfter=function(e,t){return E(e)(c=(i=Math.ceil(f/7))>c?i+1:c+1)&&(a=c,r.length=1),r.reverse();a--;)r.push(0);r.reverse()}for((c=s.length)-(a=u.length)<0&&(a=c,r=u,u=s,s=r),n=0;a;)n=(s[--a]=s[a]+u[a]+n)/m|0,s[a]%=m;for(n&&(s.unshift(n),++o),c=s.length;0==s[--c];)s.pop();return t.d=s,t.e=o,l?P(t,f):t}function x(e,t,n){if(e!==~~e||en)throw Error(u+e)}function w(e){var t,n,r,o=e.length-1,a="",i=e[0];if(o>0){for(a+=i,t=1;te.e^a.s<0?1:-1;for(t=0,n=(r=a.d.length)<(o=e.d.length)?r:o;te.d[t]^a.s<0?1:-1;return r===o?0:r>o^a.s<0?1:-1},b.decimalPlaces=b.dp=function(){var e=this,t=e.d.length-1,n=7*(t-e.e);if(t=e.d[t])for(;t%10==0;t/=10)n--;return n<0?0:n},b.dividedBy=b.div=function(e){return S(this,new this.constructor(e))},b.dividedToIntegerBy=b.idiv=function(e){var t=this.constructor;return P(S(this,new t(e),0,1),t.precision)},b.equals=b.eq=function(e){return!this.cmp(e)},b.exponent=function(){return C(this)},b.greaterThan=b.gt=function(e){return this.cmp(e)>0},b.greaterThanOrEqualTo=b.gte=function(e){return this.cmp(e)>=0},b.isInteger=b.isint=function(){return this.e>this.d.length-2},b.isNegative=b.isneg=function(){return this.s<0},b.isPositive=b.ispos=function(){return this.s>0},b.isZero=function(){return 0===this.s},b.lessThan=b.lt=function(e){return this.cmp(e)<0},b.lessThanOrEqualTo=b.lte=function(e){return this.cmp(e)<1},b.logarithm=b.log=function(e){var t,n=this,r=n.constructor,o=r.precision,i=o+5;if(void 0===e)e=new r(10);else if((e=new r(e)).s<1||e.eq(a))throw Error(s+"NaN");if(n.s<1)throw Error(s+(n.s?"NaN":"-Infinity"));return n.eq(a)?new r(0):(l=!1,t=S(A(n,i),A(e,i),i),l=!0,P(t,o))},b.minus=b.sub=function(e){var t=this;return e=new t.constructor(e),t.s==e.s?T(t,e):y(t,(e.s=-e.s,e))},b.modulo=b.mod=function(e){var t,n=this,r=n.constructor,o=r.precision;if(!(e=new r(e)).s)throw Error(s+"NaN");return n.s?(l=!1,t=S(n,e,0,1).times(e),l=!0,n.minus(t)):P(new r(n),o)},b.naturalExponential=b.exp=function(){return E(this)},b.naturalLogarithm=b.ln=function(){return A(this)},b.negated=b.neg=function(){var e=new this.constructor(this);return e.s=-e.s||0,e},b.plus=b.add=function(e){var t=this;return e=new t.constructor(e),t.s==e.s?y(t,e):T(t,(e.s=-e.s,e))},b.precision=b.sd=function(e){var t,n,r,o=this;if(void 0!==e&&e!==!!e&&1!==e&&0!==e)throw Error(u+e);if(t=C(o)+1,n=7*(r=o.d.length-1)+1,r=o.d[r]){for(;r%10==0;r/=10)n--;for(r=o.d[0];r>=10;r/=10)n++}return e&&t>n?t:n},b.squareRoot=b.sqrt=function(){var e,t,n,r,o,a,i,c=this,u=c.constructor;if(c.s<1){if(!c.s)return new u(0);throw Error(s+"NaN")}for(e=C(c),l=!1,0==(o=Math.sqrt(+c))||o==1/0?(((t=w(c.d)).length+e)%2==0&&(t+="0"),o=Math.sqrt(t),e=f((e+1)/2)-(e<0||e%2),r=new u(t=o==1/0?"5e"+e:(t=o.toExponential()).slice(0,t.indexOf("e")+1)+e)):r=new u(o.toString()),o=i=(n=u.precision)+3;;)if(r=(a=r).plus(S(c,a,i+2)).times(.5),w(a.d).slice(0,i)===(t=w(r.d)).slice(0,i)){if(t=t.slice(i-3,i+1),o==i&&"4999"==t){if(P(a,n+1,0),a.times(a).eq(c)){r=a;break}}else if("9999"!=t)break;i+=4}return l=!0,P(r,n)},b.times=b.mul=function(e){var t,n,r,o,a,i,c,s,u,d=this,f=d.constructor,p=d.d,h=(e=new f(e)).d;if(!d.s||!e.s)return new f(0);for(e.s*=d.s,n=d.e+e.e,(s=p.length)<(u=h.length)&&(a=p,p=h,h=a,i=s,s=u,u=i),a=[],r=i=s+u;r--;)a.push(0);for(r=u;--r>=0;){for(t=0,o=s+r;o>r;)c=a[o]+h[r]*p[o-r-1]+t,a[o--]=c%m|0,t=c/m|0;a[o]=(a[o]+t)%m|0}for(;!a[--i];)a.pop();return t?++n:a.shift(),e.d=a,e.e=n,l?P(e,f.precision):e},b.toDecimalPlaces=b.todp=function(e,t){var n=this,r=n.constructor;return n=new r(n),void 0===e?n:(x(e,0,i),void 0===t?t=r.rounding:x(t,0,8),P(n,e+C(n)+1,t))},b.toExponential=function(e,t){var n,r=this,o=r.constructor;return void 0===e?n=M(r,!0):(x(e,0,i),void 0===t?t=o.rounding:x(t,0,8),n=M(r=P(new o(r),e+1,t),!0,e+1)),n},b.toFixed=function(e,t){var n,r,o=this,a=o.constructor;return void 0===e?M(o):(x(e,0,i),void 0===t?t=a.rounding:x(t,0,8),n=M((r=P(new a(o),e+C(o)+1,t)).abs(),!1,e+C(r)+1),o.isneg()&&!o.isZero()?"-"+n:n)},b.toInteger=b.toint=function(){var e=this,t=e.constructor;return P(new t(e),C(e)+1,t.rounding)},b.toNumber=function(){return+this},b.toPower=b.pow=function(e){var t,n,r,o,i,c,u=this,d=u.constructor,p=+(e=new d(e));if(!e.s)return new d(a);if(!(u=new d(u)).s){if(e.s<1)throw Error(s+"Infinity");return u}if(u.eq(a))return u;if(r=d.precision,e.eq(a))return P(u,r);if(c=(t=e.e)>=(n=e.d.length-1),i=u.s,c){if((n=p<0?-p:p)<=v){for(o=new d(a),t=Math.ceil(r/7+4),l=!1;n%2&&N((o=o.times(u)).d,t),0!==(n=f(n/2));)N((u=u.times(u)).d,t);return l=!0,e.s<0?new d(a).div(o):P(o,r)}}else if(i<0)throw Error(s+"NaN");return i=i<0&&1&e.d[Math.max(t,n)]?-1:1,u.s=1,l=!1,o=e.times(A(u,r+12)),l=!0,(o=E(o)).s=i,o},b.toPrecision=function(e,t){var n,r,o=this,a=o.constructor;return void 0===e?r=M(o,(n=C(o))<=a.toExpNeg||n>=a.toExpPos):(x(e,1,i),void 0===t?t=a.rounding:x(t,0,8),r=M(o=P(new a(o),e,t),e<=(n=C(o))||n<=a.toExpNeg,e)),r},b.toSignificantDigits=b.tosd=function(e,t){var n=this.constructor;return void 0===e?(e=n.precision,t=n.rounding):(x(e,1,i),void 0===t?t=n.rounding:x(t,0,8)),P(new n(this),e,t)},b.toString=b.valueOf=b.val=b.toJSON=function(){var e=this,t=C(e),n=e.constructor;return M(e,t<=n.toExpNeg||t>=n.toExpPos)};var S=function(){function e(e,t){var n,r=0,o=e.length;for(e=e.slice();o--;)n=e[o]*t+r,e[o]=n%m|0,r=n/m|0;return r&&e.unshift(r),e}function t(e,t,n,r){var o,a;if(n!=r)a=n>r?1:-1;else for(o=a=0;ot[o]?1:-1;break}return a}function n(e,t,n){for(var r=0;n--;)e[n]-=r,r=e[n]1;)e.shift()}return function(r,o,a,i){var c,l,u,d,f,p,h,v,g,b,y,x,w,S,E,k,O,A,j=r.constructor,T=r.s==o.s?1:-1,M=r.d,N=o.d;if(!r.s)return new j(r);if(!o.s)throw Error(s+"Division by zero");for(l=r.e-o.e,O=N.length,E=M.length,v=(h=new j(T)).d=[],u=0;N[u]==(M[u]||0);)++u;if(N[u]>(M[u]||0)&&--l,(x=null==a?a=j.precision:i?a+(C(r)-C(o))+1:a)<0)return new j(0);if(x=x/7+2|0,u=0,1==O)for(d=0,N=N[0],x++;(u1&&(N=e(N,d),M=e(M,d),O=N.length,E=M.length),S=O,b=(g=M.slice(0,O)).length;b=m/2&&++k;do{d=0,(c=t(N,g,O,b))<0?(y=g[0],O!=b&&(y=y*m+(g[1]||0)),(d=y/k|0)>1?(d>=m&&(d=m-1),1==(c=t(f=e(N,d),g,p=f.length,b=g.length))&&(d--,n(f,O16)throw Error(d+C(e));if(!e.s)return new f(a);for(null==t?(l=!1,c=h):c=t,i=new f(.03125);e.abs().gte(.1);)e=e.times(i),u+=5;for(c+=Math.log(p(2,u))/Math.LN10*2+5|0,n=r=o=new f(a),f.precision=c;;){if(r=P(r.times(e),c),n=n.times(++s),w((i=o.plus(S(r,n,c))).d).slice(0,c)===w(o.d).slice(0,c)){for(;u--;)o=P(o.times(o),c);return f.precision=h,null==t?(l=!0,P(o,h)):o}o=i}}function C(e){for(var t=7*e.e,n=e.d[0];n>=10;n/=10)t++;return t}function k(e,t,n){if(t>e.LN10.sd())throw l=!0,n&&(e.precision=n),Error(s+"LN10 precision limit exceeded");return P(new e(e.LN10),t)}function O(e){for(var t="";e--;)t+="0";return t}function A(e,t){var n,r,o,i,c,u,d,f,p,h=1,m=e,v=m.d,g=m.constructor,b=g.precision;if(m.s<1)throw Error(s+(m.s?"NaN":"-Infinity"));if(m.eq(a))return new g(0);if(null==t?(l=!1,f=b):f=t,m.eq(10))return null==t&&(l=!0),k(g,f);if(f+=10,g.precision=f,r=(n=w(v)).charAt(0),i=C(m),!(Math.abs(i)<15e14))return d=k(g,f+2,b).times(i+""),m=A(new g(r+"."+n.slice(1)),f-10).plus(d),g.precision=b,null==t?(l=!0,P(m,b)):m;for(;r<7&&1!=r||1==r&&n.charAt(1)>3;)r=(n=w((m=m.times(e)).d)).charAt(0),h++;for(i=C(m),r>1?(m=new g("0."+n),i++):m=new g(r+"."+n.slice(1)),u=c=m=S(m.minus(a),m.plus(a),f),p=P(m.times(m),f),o=3;;){if(c=P(c.times(p),f),w((d=u.plus(S(c,new g(o),f))).d).slice(0,f)===w(u.d).slice(0,f))return u=u.times(2),0!==i&&(u=u.plus(k(g,f+2,b).times(i+""))),u=S(u,new g(h),f),g.precision=b,null==t?(l=!0,P(u,b)):u;u=d,o+=2}}function j(e,t){var n,r,o;for((n=t.indexOf("."))>-1&&(t=t.replace(".","")),(r=t.search(/e/i))>0?(n<0&&(n=r),n+=+t.slice(r+1),t=t.substring(0,r)):n<0&&(n=t.length),r=0;48===t.charCodeAt(r);)++r;for(o=t.length;48===t.charCodeAt(o-1);)--o;if(t=t.slice(r,o)){if(o-=r,n=n-r-1,e.e=f(n/7),e.d=[],r=(n+1)%7,n<0&&(r+=7),rg||e.e<-g))throw Error(d+n)}else e.s=0,e.e=0,e.d=[0];return e}function P(e,t,n){var r,o,a,i,c,s,u,h,v=e.d;for(i=1,a=v[0];a>=10;a/=10)i++;if((r=t-i)<0)r+=7,o=t,u=v[h=0];else{if((h=Math.ceil((r+1)/7))>=(a=v.length))return e;for(u=a=v[h],i=1;a>=10;a/=10)i++;o=(r%=7)-7+i}if(void 0!==n&&(c=u/(a=p(10,i-o-1))%10|0,s=t<0||void 0!==v[h+1]||u%a,s=n<4?(c||s)&&(0==n||n==(e.s<0?3:2)):c>5||5==c&&(4==n||s||6==n&&(r>0?o>0?u/p(10,i-o):0:v[h-1])%10&1||n==(e.s<0?8:7))),t<1||!v[0])return s?(a=C(e),v.length=1,t=t-a-1,v[0]=p(10,(7-t%7)%7),e.e=f(-t/7)||0):(v.length=1,v[0]=e.e=e.s=0),e;if(0==r?(v.length=h,a=1,h--):(v.length=h+1,a=p(10,7-r),v[h]=o>0?(u/p(10,i-o)%p(10,o)|0)*a:0),s)for(;;){if(0==h){(v[0]+=a)==m&&(v[0]=1,++e.e);break}if(v[h]+=a,v[h]!=m)break;v[h--]=0,a=1}for(r=v.length;0===v[--r];)v.pop();if(l&&(e.e>g||e.e<-g))throw Error(d+C(e));return e}function T(e,t){var n,r,o,a,i,c,s,u,d,f,p=e.constructor,h=p.precision;if(!e.s||!t.s)return t.s?t.s=-t.s:t=new p(e),l?P(t,h):t;if(s=e.d,f=t.d,r=t.e,u=e.e,s=s.slice(),i=u-r){for((d=i<0)?(n=s,i=-i,c=f.length):(n=f,r=u,c=s.length),i>(o=Math.max(Math.ceil(h/7),c)+2)&&(i=o,n.length=1),n.reverse(),o=i;o--;)n.push(0);n.reverse()}else{for((d=(o=s.length)<(c=f.length))&&(c=o),o=0;o0;--o)s[c++]=0;for(o=f.length;o>i;){if(s[--o]0?a=a.charAt(0)+"."+a.slice(1)+O(r):i>1&&(a=a.charAt(0)+"."+a.slice(1)),a=a+(o<0?"e":"e+")+o):o<0?(a="0."+O(-o-1)+a,n&&(r=n-i)>0&&(a+=O(r))):o>=i?(a+=O(o+1-i),n&&(r=n-o-1)>0&&(a=a+"."+O(r))):((r=o+1)0&&(o+1===i&&(a+="."),a+=O(r))),e.s<0?"-"+a:a}function N(e,t){if(e.length>t)return e.length=t,!0}function _(e){if(!e||"object"!==typeof e)throw Error(s+"Object expected");var t,n,r,o=["precision",1,i,"rounding",0,8,"toExpNeg",-1/0,0,"toExpPos",0,1/0];for(t=0;t=o[t+1]&&r<=o[t+2]))throw Error(u+n+": "+r);this[n]=r}if(void 0!==(r=e[n="LN10"])){if(r!=Math.LN10)throw Error(u+n+": "+r);this[n]=new this(r)}return this}c=function e(t){var n,r,o;function a(e){var t=this;if(!(t instanceof a))return new a(e);if(t.constructor=a,e instanceof a)return t.s=e.s,t.e=e.e,void(t.d=(e=e.d)?e.slice():e);if("number"===typeof e){if(0*e!==0)throw Error(u+e);if(e>0)t.s=1;else{if(!(e<0))return t.s=0,t.e=0,void(t.d=[0]);e=-e,t.s=-1}return e===~~e&&e<1e7?(t.e=0,void(t.d=[e])):j(t,e.toString())}if("string"!==typeof e)throw Error(u+e);if(45===e.charCodeAt(0)?(e=e.slice(1),t.s=-1):t.s=1,!h.test(e))throw Error(u+e);j(t,e)}if(a.prototype=b,a.ROUND_UP=0,a.ROUND_DOWN=1,a.ROUND_CEIL=2,a.ROUND_FLOOR=3,a.ROUND_HALF_UP=4,a.ROUND_HALF_DOWN=5,a.ROUND_HALF_EVEN=6,a.ROUND_HALF_CEIL=7,a.ROUND_HALF_FLOOR=8,a.clone=e,a.config=a.set=_,void 0===t&&(t={}),t)for(o=["precision","rounding","toExpNeg","toExpPos","LN10"],n=0;n65535&&(e-=65536,t+=String.fromCharCode(e>>>10&1023|55296),e=56320|1023&e),t+=String.fromCharCode(e)};t.default=function(e){return e>=55296&&e<=57343||e>1114111?"\ufffd":(e in o.default&&(e=o.default[e]),a(e))}},2056:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.escapeUTF8=t.escape=t.encodeNonAsciiHTML=t.encodeHTML=t.encodeXML=void 0;var o=u(r(n(2586)).default),a=d(o);t.encodeXML=v(o);var i,c,l=u(r(n(9323)).default),s=d(l);function u(e){return Object.keys(e).sort().reduce((function(t,n){return t[e[n]]="&"+n+";",t}),{})}function d(e){for(var t=[],n=[],r=0,o=Object.keys(e);r1?p(e):e.charCodeAt(0)).toString(16).toUpperCase()+";"}var m=new RegExp(a.source+"|"+f.source,"g");function v(e){return function(t){return t.replace(m,(function(t){return e[t]||h(t)}))}}t.escape=function(e){return e.replace(m,h)},t.escapeUTF8=function(e){return e.replace(a,h)}},4191:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.decodeXMLStrict=t.decodeHTML5Strict=t.decodeHTML4Strict=t.decodeHTML5=t.decodeHTML4=t.decodeHTMLStrict=t.decodeHTML=t.decodeXML=t.encodeHTML5=t.encodeHTML4=t.escapeUTF8=t.escape=t.encodeNonAsciiHTML=t.encodeHTML=t.encodeXML=t.encode=t.decodeStrict=t.decode=void 0;var r=n(1298),o=n(2056);t.decode=function(e,t){return(!t||t<=0?r.decodeXML:r.decodeHTML)(e)},t.decodeStrict=function(e,t){return(!t||t<=0?r.decodeXML:r.decodeHTMLStrict)(e)},t.encode=function(e,t){return(!t||t<=0?o.encodeXML:o.encodeHTML)(e)};var a=n(2056);Object.defineProperty(t,"encodeXML",{enumerable:!0,get:function(){return a.encodeXML}}),Object.defineProperty(t,"encodeHTML",{enumerable:!0,get:function(){return a.encodeHTML}}),Object.defineProperty(t,"encodeNonAsciiHTML",{enumerable:!0,get:function(){return a.encodeNonAsciiHTML}}),Object.defineProperty(t,"escape",{enumerable:!0,get:function(){return a.escape}}),Object.defineProperty(t,"escapeUTF8",{enumerable:!0,get:function(){return a.escapeUTF8}}),Object.defineProperty(t,"encodeHTML4",{enumerable:!0,get:function(){return a.encodeHTML}}),Object.defineProperty(t,"encodeHTML5",{enumerable:!0,get:function(){return a.encodeHTML}});var i=n(1298);Object.defineProperty(t,"decodeXML",{enumerable:!0,get:function(){return i.decodeXML}}),Object.defineProperty(t,"decodeHTML",{enumerable:!0,get:function(){return i.decodeHTML}}),Object.defineProperty(t,"decodeHTMLStrict",{enumerable:!0,get:function(){return i.decodeHTMLStrict}}),Object.defineProperty(t,"decodeHTML4",{enumerable:!0,get:function(){return i.decodeHTML}}),Object.defineProperty(t,"decodeHTML5",{enumerable:!0,get:function(){return i.decodeHTML}}),Object.defineProperty(t,"decodeHTML4Strict",{enumerable:!0,get:function(){return i.decodeHTMLStrict}}),Object.defineProperty(t,"decodeHTML5Strict",{enumerable:!0,get:function(){return i.decodeHTMLStrict}}),Object.defineProperty(t,"decodeXMLStrict",{enumerable:!0,get:function(){return i.decodeXML}})},1584:function(e){"use strict";var t=/["'&<>]/;e.exports=function(e){var n,r=""+e,o=t.exec(r);if(!o)return r;var a="",i=0,c=0;for(i=o.index;i0;)if(!n(e[o],t[o],r))return!1;return!0}function d(e,t,n,r){var o=e.size===t.size;if(o&&e.size){var a={};e.forEach((function(e,i){if(o){var c=!1,l=0;t.forEach((function(t,o){c||a[l]||(c=n(i,o,r)&&n(e,t,r))&&(a[l]=!0),l++})),o=c}}))}return o}var f="_owner",p=Function.prototype.bind.call(Function.prototype.call,Object.prototype.hasOwnProperty);function h(e,t,r,o){var a=n(e),c=a.length;if(n(t).length!==c)return!1;if(c)for(var l=void 0;c-- >0;){if((l=a[c])===f){var s=i(e),u=i(t);if((s||u)&&s!==u)return!1}if(!p(t,l)||!r(e[l],t[l],o))return!1}return!0}function m(e,t){return e.source===t.source&&e.global===t.global&&e.ignoreCase===t.ignoreCase&&e.multiline===t.multiline&&e.unicode===t.unicode&&e.sticky===t.sticky&&e.lastIndex===t.lastIndex}function v(e,t,n,r){var o=e.size===t.size;if(o&&e.size){var a={};e.forEach((function(e){if(o){var i=!1,c=0;t.forEach((function(t){i||a[c]||(i=n(e,t,r))&&(a[c]=!0),c++})),o=i}}))}return o}var g="function"===typeof Map,b="function"===typeof Set;function y(e){var t="function"===typeof e?e(n):n;function n(e,n,i){if(e===n)return!0;if(e&&n&&"object"===typeof e&&"object"===typeof n){if(o(e)&&o(n))return h(e,n,t,i);var c=Array.isArray(e),l=Array.isArray(n);return c||l?c===l&&u(e,n,t,i):(c=e instanceof Date,l=n instanceof Date,c||l?c===l&&r(e.getTime(),n.getTime()):(c=e instanceof RegExp,l=n instanceof RegExp,c||l?c===l&&m(e,n):a(e)||a(n)?e===n:g&&(c=e instanceof Map,l=n instanceof Map,c||l)?c===l&&d(e,n,t,i):b&&(c=e instanceof Set,l=n instanceof Set,c||l)?c===l&&v(e,n,t,i):h(e,n,t,i)))}return e!==e&&n!==n}return n}var x=y(),w=y((function(){return r})),S=y(s()),E=y(s(r));e.circularDeepEqual=S,e.circularShallowEqual=E,e.createCustomEqual=y,e.deepEqual=x,e.sameValueZeroEqual=r,e.shallowEqual=w,Object.defineProperty(e,"__esModule",{value:!0})}(t)},908:function(e,t,n){var r=n(8136)(n(7009),"DataView");e.exports=r},9676:function(e,t,n){var r=n(5403),o=n(2747),a=n(6037),i=n(4154),c=n(7728);function l(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1}},2683:function(e){e.exports=function(e,t,n){for(var r=-1,o=null==e?0:e.length;++r0&&a(u)?n>1?e(u,n-1,a,i,c):r(c,u):i||(c[c.length]=u)}return c}},5099:function(e,t,n){var r=n(372)();e.exports=r},5358:function(e,t,n){var r=n(5099),o=n(2742);e.exports=function(e,t){return e&&r(e,t,o)}},8667:function(e,t,n){var r=n(3082),o=n(9793);e.exports=function(e,t){for(var n=0,a=(t=r(t,e)).length;null!=e&&nt}},529:function(e){e.exports=function(e,t){return null!=e&&t in Object(e)}},4842:function(e,t,n){var r=n(2045),o=n(505),a=n(7167);e.exports=function(e,t,n){return t===t?a(e,t,n):r(e,o,n)}},4906:function(e,t,n){var r=n(9066),o=n(3141);e.exports=function(e){return o(e)&&"[object Arguments]"==r(e)}},1848:function(e,t,n){var r=n(3355),o=n(3141);e.exports=function e(t,n,a,i,c){return t===n||(null==t||null==n||!o(t)&&!o(n)?t!==t&&n!==n:r(t,n,a,i,e,c))}},3355:function(e,t,n){var r=n(2854),o=n(5305),a=n(2206),i=n(8078),c=n(8383),l=n(3629),s=n(5174),u=n(9102),d="[object Arguments]",f="[object Array]",p="[object Object]",h=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,m,v,g){var b=l(e),y=l(t),x=b?f:c(e),w=y?f:c(t),S=(x=x==d?p:x)==p,E=(w=w==d?p:w)==p,C=x==w;if(C&&s(e)){if(!s(t))return!1;b=!0,S=!1}if(C&&!S)return g||(g=new r),b||u(e)?o(e,t,n,m,v,g):a(e,t,x,n,m,v,g);if(!(1&n)){var k=S&&h.call(e,"__wrapped__"),O=E&&h.call(t,"__wrapped__");if(k||O){var A=k?e.value():e,j=O?t.value():t;return g||(g=new r),v(A,j,n,m,g)}}return!!C&&(g||(g=new r),i(e,t,n,m,v,g))}},8856:function(e,t,n){var r=n(2854),o=n(1848);e.exports=function(e,t,n,a){var i=n.length,c=i,l=!a;if(null==e)return!c;for(e=Object(e);i--;){var s=n[i];if(l&&s[2]?s[1]!==e[s[0]]:!(s[0]in e))return!1}for(;++io?0:o+t),(n=n>o?o:n)<0&&(n+=o),o=t>n?0:n-t>>>0,t>>>=0;for(var a=Array(o);++r=200){var m=t?null:c(e);if(m)return l(m);f=!1,u=i,h=new r}else h=t?[]:p;e:for(;++s=o?e:r(e,t,n)}},8558:function(e,t,n){var r=n(152);e.exports=function(e,t){if(e!==t){var n=void 0!==e,o=null===e,a=e===e,i=r(e),c=void 0!==t,l=null===t,s=t===t,u=r(t);if(!l&&!u&&!i&&e>t||i&&c&&s&&!l&&!u||o&&c&&s||!n&&s||!a)return 1;if(!o&&!i&&!u&&e=l?s:s*("desc"==n[o]?-1:1)}return e.index-t.index}},5525:function(e,t,n){var r=n(7009)["__core-js_shared__"];e.exports=r},7056:function(e,t,n){var r=n(1473);e.exports=function(e,t){return function(n,o){if(null==n)return n;if(!r(n))return e(n,o);for(var a=n.length,i=t?a:-1,c=Object(n);(t?i--:++i-1?c[l?t[s]:s]:void 0}}},6381:function(e,t,n){var r=n(7255),o=n(3195),a=n(1495);e.exports=function(e){return function(t,n,i){return i&&"number"!=typeof i&&o(t,n,i)&&(n=i=void 0),t=a(t),void 0===n?(n=t,t=0):n=a(n),i=void 0===i?tu))return!1;var f=l.get(e),p=l.get(t);if(f&&p)return f==t&&p==e;var h=-1,m=!0,v=2&n?new r:void 0;for(l.set(e,t),l.set(t,e);++h-1&&e%1==0&&e-1}},7109:function(e,t,n){var r=n(7112);e.exports=function(e,t){var n=this.__data__,o=r(n,e);return o<0?(++this.size,n.push([e,t])):n[o][1]=t,this}},4086:function(e,t,n){var r=n(9676),o=n(8384),a=n(5797);e.exports=function(){this.size=0,this.__data__={hash:new r,map:new(a||o),string:new r}}},9255:function(e,t,n){var r=n(2799);e.exports=function(e){var t=r(this,e).delete(e);return this.size-=t?1:0,t}},9186:function(e,t,n){var r=n(2799);e.exports=function(e){return r(this,e).get(e)}},3423:function(e,t,n){var r=n(2799);e.exports=function(e){return r(this,e).has(e)}},3739:function(e,t,n){var r=n(2799);e.exports=function(e,t){var n=r(this,e),o=n.size;return n.set(e,t),this.size+=n.size==o?0:1,this}},234:function(e){e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}},284:function(e){e.exports=function(e,t){return function(n){return null!=n&&(n[e]===t&&(void 0!==t||e in Object(n)))}}},4634:function(e,t,n){var r=n(9151);e.exports=function(e){var t=r(e,(function(e){return 500===n.size&&n.clear(),e})),n=t.cache;return t}},9620:function(e,t,n){var r=n(8136)(Object,"create");e.exports=r},8836:function(e,t,n){var r=n(2709)(Object.keys,Object);e.exports=r},9494:function(e,t,n){e=n.nmd(e);var r=n(1032),o=t&&!t.nodeType&&t,a=o&&e&&!e.nodeType&&e,i=a&&a.exports===o&&r.process,c=function(){try{var e=a&&a.require&&a.require("util").types;return e||i&&i.binding&&i.binding("util")}catch(t){}}();e.exports=c},3581:function(e){var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},2709:function(e){e.exports=function(e,t){return function(n){return e(t(n))}}},4262:function(e,t,n){var r=n(3665),o=Math.max;e.exports=function(e,t,n){return t=o(void 0===t?e.length-1:t,0),function(){for(var a=arguments,i=-1,c=o(a.length-t,0),l=Array(c);++i0){if(++n>=800)return arguments[0]}else n=0;return e.apply(void 0,arguments)}}},511:function(e,t,n){var r=n(8384);e.exports=function(){this.__data__=new r,this.size=0}},835:function(e){e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},707:function(e){e.exports=function(e){return this.__data__.get(e)}},8832:function(e){e.exports=function(e){return this.__data__.has(e)}},5077:function(e,t,n){var r=n(8384),o=n(5797),a=n(8059);e.exports=function(e,t){var n=this.__data__;if(n instanceof r){var i=n.__data__;if(!o||i.length<199)return i.push([e,t]),this.size=++n.size,this;n=this.__data__=new a(i)}return n.set(e,t),this.size=n.size,this}},7167:function(e){e.exports=function(e,t,n){for(var r=n-1,o=e.length;++r=t||n<0||v&&e-h>=u}function w(){var e=o();if(x(e))return S(e);f=setTimeout(w,function(e){var n=t-(e-p);return v?c(n,u-(e-h)):n}(e))}function S(e){return f=void 0,g&&l?b(e):(l=s=void 0,d)}function E(){var e=o(),n=x(e);if(l=arguments,s=this,p=e,n){if(void 0===f)return y(p);if(v)return clearTimeout(f),f=setTimeout(w,t),b(p)}return void 0===f&&(f=setTimeout(w,t)),d}return t=a(t)||0,r(n)&&(m=!!n.leading,u=(v="maxWait"in n)?i(a(n.maxWait)||0,t):u,g="trailing"in n?!!n.trailing:g),E.cancel=function(){void 0!==f&&clearTimeout(f),h=0,l=p=s=f=void 0},E.flush=function(){return void 0===f?d:S(o())},E}},9231:function(e){e.exports=function(e,t){return e===t||e!==e&&t!==t}},2730:function(e,t,n){var r=n(4277),o=n(9863),a=n(6025),i=n(3629),c=n(3195);e.exports=function(e,t,n){var l=i(e)?r:o;return n&&c(e,t,n)&&(t=void 0),l(e,a(t,3))}},1211:function(e,t,n){var r=n(5481)(n(1475));e.exports=r},1475:function(e,t,n){var r=n(2045),o=n(6025),a=n(9753),i=Math.max;e.exports=function(e,t,n){var c=null==e?0:e.length;if(!c)return-1;var l=null==n?0:a(n);return l<0&&(l=i(c+l,0)),r(e,o(t,3),l)}},5008:function(e,t,n){var r=n(5182),o=n(2034);e.exports=function(e,t){return r(o(e,t),1)}},6181:function(e,t,n){var r=n(8667);e.exports=function(e,t,n){var o=null==e?void 0:r(e,t);return void 0===o?n:o}},5658:function(e,t,n){var r=n(529),o=n(6417);e.exports=function(e,t){return null!=e&&o(e,t,r)}},2100:function(e){e.exports=function(e){return e}},4963:function(e,t,n){var r=n(4906),o=n(3141),a=Object.prototype,i=a.hasOwnProperty,c=a.propertyIsEnumerable,l=r(function(){return arguments}())?r:function(e){return o(e)&&i.call(e,"callee")&&!c.call(e,"callee")};e.exports=l},3629:function(e){var t=Array.isArray;e.exports=t},1473:function(e,t,n){var r=n(4786),o=n(4635);e.exports=function(e){return null!=e&&o(e.length)&&!r(e)}},5127:function(e,t,n){var r=n(9066),o=n(3141);e.exports=function(e){return!0===e||!1===e||o(e)&&"[object Boolean]"==r(e)}},5174:function(e,t,n){e=n.nmd(e);var r=n(7009),o=n(9488),a=t&&!t.nodeType&&t,i=a&&e&&!e.nodeType&&e,c=i&&i.exports===a?r.Buffer:void 0,l=(c?c.isBuffer:void 0)||o;e.exports=l},8111:function(e,t,n){var r=n(1848);e.exports=function(e,t){return r(e,t)}},4786:function(e,t,n){var r=n(9066),o=n(8092);e.exports=function(e){if(!o(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},4635:function(e){e.exports=function(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}},2066:function(e,t,n){var r=n(298);e.exports=function(e){return r(e)&&e!=+e}},5633:function(e){e.exports=function(e){return null==e}},298:function(e,t,n){var r=n(9066),o=n(3141);e.exports=function(e){return"number"==typeof e||o(e)&&"[object Number]"==r(e)}},8092:function(e){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},3141:function(e){e.exports=function(e){return null!=e&&"object"==typeof e}},3977:function(e,t,n){var r=n(9066),o=n(1137),a=n(3141),i=Function.prototype,c=Object.prototype,l=i.toString,s=c.hasOwnProperty,u=l.call(Object);e.exports=function(e){if(!a(e)||"[object Object]"!=r(e))return!1;var t=o(e);if(null===t)return!0;var n=s.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&l.call(n)==u}},6769:function(e,t,n){var r=n(9066),o=n(3629),a=n(3141);e.exports=function(e){return"string"==typeof e||!o(e)&&a(e)&&"[object String]"==r(e)}},152:function(e,t,n){var r=n(9066),o=n(3141);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},9102:function(e,t,n){var r=n(8150),o=n(6194),a=n(9494),i=a&&a.isTypedArray,c=i?o(i):r;e.exports=c},2742:function(e,t,n){var r=n(7538),o=n(3654),a=n(1473);e.exports=function(e){return a(e)?r(e):o(e)}},5727:function(e){e.exports=function(e){var t=null==e?0:e.length;return t?e[t-1]:void 0}},2034:function(e,t,n){var r=n(8950),o=n(6025),a=n(3849),i=n(3629);e.exports=function(e,t){return(i(e)?r:a)(e,o(t,3))}},7702:function(e,t,n){var r=n(2526),o=n(5358),a=n(6025);e.exports=function(e,t){var n={};return t=a(t,3),o(e,(function(e,o,a){r(n,o,t(e,o,a))})),n}},9627:function(e,t,n){var r=n(3079),o=n(1954),a=n(2100);e.exports=function(e){return e&&e.length?r(e,a,o):void 0}},8559:function(e,t,n){var r=n(3079),o=n(1954),a=n(6025);e.exports=function(e,t){return e&&e.length?r(e,a(t,2),o):void 0}},9151:function(e,t,n){var r=n(8059);function o(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new TypeError("Expected a function");var n=function n(){var r=arguments,o=t?t.apply(this,r):r[0],a=n.cache;if(a.has(o))return a.get(o);var i=e.apply(this,r);return n.cache=a.set(o,i)||a,i};return n.cache=new(o.Cache||r),n}o.Cache=r,e.exports=o},6452:function(e,t,n){var r=n(3079),o=n(2580),a=n(2100);e.exports=function(e){return e&&e.length?r(e,a,o):void 0}},3638:function(e,t,n){var r=n(3079),o=n(6025),a=n(2580);e.exports=function(e,t){return e&&e.length?r(e,o(t,2),a):void 0}},9694:function(e){e.exports=function(){}},72:function(e,t,n){var r=n(7009);e.exports=function(){return r.Date.now()}},38:function(e,t,n){var r=n(9586),o=n(4084),a=n(5823),i=n(9793);e.exports=function(e){return a(e)?r(i(e)):o(e)}},6222:function(e,t,n){var r=n(6381)();e.exports=r},4064:function(e,t,n){var r=n(7897),o=n(6025),a=n(9204),i=n(3629),c=n(3195);e.exports=function(e,t,n){var l=i(e)?r:a;return n&&c(e,t,n)&&(t=void 0),l(e,o(t,3))}},4286:function(e,t,n){var r=n(5182),o=n(3226),a=n(8794),i=n(3195),c=a((function(e,t){if(null==e)return[];var n=t.length;return n>1&&i(e,t[0],t[1])?t=[]:n>2&&i(t[0],t[1],t[2])&&(t=[t[0]]),o(e,r(t,1),[])}));e.exports=c},8174:function(e){e.exports=function(){return[]}},9488:function(e){e.exports=function(){return!1}},3038:function(e,t,n){var r=n(8573),o=n(8092);e.exports=function(e,t,n){var a=!0,i=!0;if("function"!=typeof e)throw new TypeError("Expected a function");return o(n)&&(a="leading"in n?!!n.leading:a,i="trailing"in n?!!n.trailing:i),r(e,t,{leading:a,maxWait:t,trailing:i})}},1495:function(e,t,n){var r=n(2582),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e===e?e:0:0===e?e:0}},9753:function(e,t,n){var r=n(1495);e.exports=function(e){var t=r(e),n=t%1;return t===t?n?t-n:t:0}},2582:function(e,t,n){var r=n(821),o=n(8092),a=n(152),i=/^[-+]0x[0-9a-f]+$/i,c=/^0b[01]+$/i,l=/^0o[0-7]+$/i,s=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(a(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var n=c.test(e);return n||l.test(e)?s(e.slice(2),n?2:8):i.test(e)?NaN:+e}},3518:function(e,t,n){var r=n(2446);e.exports=function(e){return null==e?"":r(e)}},6339:function(e,t,n){var r=n(6025),o=n(9602);e.exports=function(e,t){return e&&e.length?o(e,r(t,2)):[]}},2085:function(e,t,n){var r=n(322)("toUpperCase");e.exports=r},888:function(e,t,n){"use strict";var r=n(9047);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},2007:function(e,t,n){e.exports=n(888)()},9047:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},3841:function(e,t,n){e=n.nmd(e),function(n,r){var o=function(){var e=null,t={};m();var n=[],r=function t(r){if(void 0!==(r=r||{}).seed&&null!==r.seed&&r.seed===parseInt(r.seed,10))e=r.seed;else if("string"===typeof r.seed)e=y(r.seed);else{if(void 0!==r.seed&&null!==r.seed)throw new TypeError("The seed value must be an integer or string");e=null}var l,s;if(null!==r.count&&void 0!==r.count){for(var u=r.count,d=[],f=0;fd.length;){var p=t(r);null!==e&&(r.seed=e),d.push(p)}return r.count=u,d}return c([l=o(r),s=a(l,r),i(l,s,r)],r)};function o(e){if(n.length>0){var t=f(a=x(e.hue)),r=(a[1]-a[0])/n.length,o=parseInt((t-a[0])/r);return!0===n[o]?o=(o+2)%n.length:n[o]=!0,(t=f(a=[(a[0]+o*r)%359,(a[0]+(o+1)*r)%359]))<0&&(t=360+t),t}var a;return(t=f(a=s(e.hue)))<0&&(t=360+t),t}function a(e,t){if("monochrome"===t.hue)return 0;if("random"===t.luminosity)return f([0,100]);var n=u(e),r=n[0],o=n[1];switch(t.luminosity){case"bright":r=55;break;case"dark":r=o-10;break;case"light":o=55}return f([r,o])}function i(e,t,n){var r=l(e,t),o=100;switch(n.luminosity){case"dark":o=r+20;break;case"light":r=(o+r)/2;break;case"random":r=0,o=100}return f([r,o])}function c(e,t){switch(t.format){case"hsvArray":return e;case"hslArray":return b(e);case"hsl":var n=b(e);return"hsl("+n[0]+", "+n[1]+"%, "+n[2]+"%)";case"hsla":var r=b(e),o=t.alpha||Math.random();return"hsla("+r[0]+", "+r[1]+"%, "+r[2]+"%, "+o+")";case"rgbArray":return v(e);case"rgb":return"rgb("+v(e).join(", ")+")";case"rgba":var a=v(e);o=t.alpha||Math.random();return"rgba("+a.join(", ")+", "+o+")";default:return p(e)}}function l(e,t){for(var n=d(e).lowerBounds,r=0;r=o&&t<=i){var l=(c-a)/(i-o);return l*t+(a-l*o)}}return 0}function s(e){if("number"===typeof parseInt(e)){var n=parseInt(e);if(n<360&&n>0)return[n,n]}if("string"===typeof e)if(t[e]){var r=t[e];if(r.hueRange)return r.hueRange}else if(e.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)){var o=g(e)[0];return[o,o]}return[0,360]}function u(e){return d(e).saturationRange}function d(e){for(var n in e>=334&&e<=360&&(e-=360),t){var r=t[n];if(r.hueRange&&e>=r.hueRange[0]&&e<=r.hueRange[1])return t[n]}return"Color not found"}function f(t){if(null===e){var n=.618033988749895,r=Math.random();return r+=n,r%=1,Math.floor(t[0]+r*(t[1]+1-t[0]))}var o=t[1]||1,a=t[0]||0,i=(e=(9301*e+49297)%233280)/233280;return Math.floor(a+i*(o-a))}function p(e){var t=v(e);function n(e){var t=e.toString(16);return 1==t.length?"0"+t:t}return"#"+n(t[0])+n(t[1])+n(t[2])}function h(e,n,r){var o=r[0][0],a=r[r.length-1][0],i=r[r.length-1][1],c=r[0][1];t[e]={hueRange:n,lowerBounds:r,saturationRange:[o,a],brightnessRange:[i,c]}}function m(){h("monochrome",null,[[0,0],[100,0]]),h("red",[-26,18],[[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]),h("orange",[18,46],[[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]),h("yellow",[46,62],[[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]),h("green",[62,178],[[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]),h("blue",[178,257],[[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]),h("purple",[257,282],[[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]),h("pink",[282,334],[[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]])}function v(e){var t=e[0];0===t&&(t=1),360===t&&(t=359),t/=360;var n=e[1]/100,r=e[2]/100,o=Math.floor(6*t),a=6*t-o,i=r*(1-n),c=r*(1-a*n),l=r*(1-(1-a)*n),s=256,u=256,d=256;switch(o){case 0:s=r,u=l,d=i;break;case 1:s=c,u=r,d=i;break;case 2:s=i,u=r,d=l;break;case 3:s=i,u=c,d=r;break;case 4:s=l,u=i,d=r;break;case 5:s=r,u=i,d=c}return[Math.floor(255*s),Math.floor(255*u),Math.floor(255*d)]}function g(e){e=3===(e=e.replace(/^#/,"")).length?e.replace(/(.)/g,"$1$1"):e;var t=parseInt(e.substr(0,2),16)/255,n=parseInt(e.substr(2,2),16)/255,r=parseInt(e.substr(4,2),16)/255,o=Math.max(t,n,r),a=o-Math.min(t,n,r),i=o?a/o:0;switch(o){case t:return[(n-r)/a%6*60||0,i,o];case n:return[60*((r-t)/a+2)||0,i,o];case r:return[60*((t-n)/a+4)||0,i,o]}}function b(e){var t=e[0],n=e[1]/100,r=e[2]/100,o=(2-n)*r;return[t,Math.round(n*r/(o<1?o:2-o)*1e4)/100,o/2*100]}function y(e){for(var t=0,n=0;n!==e.length&&!(t>=Number.MAX_SAFE_INTEGER);n++)t+=e.charCodeAt(n);return t}function x(e){if(isNaN(e)){if("string"===typeof e)if(t[e]){var n=t[e];if(n.hueRange)return n.hueRange}else if(e.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)){return d(g(e)[0]).hueRange}}else{var r=parseInt(e);if(r<360&&r>0)return d(e).hueRange}return[0,360]}return r}();e&&e.exports&&(t=e.exports=o),t.randomColor=o}()},4463:function(e,t,n){"use strict";var r=n(2791),o=n(5296);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n
\"\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 91 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 92 |\u001b[39m expect(result)\u001b[33m.\u001b[39mtoContain(\u001b[32m'xmlns=\"http://example.org\"'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 93 |\u001b[39m expect(result)\u001b[33m.\u001b[39mtoContain(\u001b[32m'\u001b[39m {\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/JSONToXML.test.ts\u001b[39m\u001b[0m\u001b[2m:93:22)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mJSONToXML › serialize › should handle nested elements\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\n Expected substring: \u001b[32m\"Child Text\"\u001b[39m\n Received string: \u001b[31m\" Child Text \"\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 179 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 180 |\u001b[39m expect(result)\u001b[33m.\u001b[39mtoContain(\u001b[32m''\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 181 |\u001b[39m expect(result)\u001b[33m.\u001b[39mtoContain(\u001b[32m'Child Text'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 182 |\u001b[39m expect(result)\u001b[33m.\u001b[39mtoContain(\u001b[32m''\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 183 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 184 |\u001b[39m \u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/JSONToXML.test.ts\u001b[39m\u001b[0m\u001b[2m:181:22)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mJSONToXML › serialize › should work with the XMLToJSON parser in a round-trip\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\n Expected substring: \u001b[32m\"The Great Gatsby\"\u001b[39m\n Received string: \u001b[31m\" The Great Gatsby F. Scott Fitzgerald 1925 that should be preserved]]>\"\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 203 |\u001b[39m expect(resultXml)\u001b[33m.\u001b[39mtoContain(\u001b[32m''\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 204 |\u001b[39m expect(resultXml)\u001b[33m.\u001b[39mtoContain(\u001b[32m''\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 205 |\u001b[39m expect(resultXml)\u001b[33m.\u001b[39mtoContain(\u001b[32m'The Great Gatsby'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 206 |\u001b[39m expect(resultXml)\u001b[33m.\u001b[39mtoContain(\u001b[32m'F. Scott Fitzgerald'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 207 |\u001b[39m expect(resultXml)\u001b[33m.\u001b[39mtoContain(\u001b[32m'1925'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 208 |\u001b[39m expect(resultXml)\u001b[33m.\u001b[39mtoContain(\u001b[32m''\u001b[39m)\u001b[33m;\u001b[39m\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/JSONToXML.test.ts\u001b[39m\u001b[0m\u001b[2m:205:25)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mJSONToXML › configuration tests › should not format XML (pretty print) when disabled\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\n Expected: \u001b[32m1\u001b[39m\n Received: \u001b[31m2\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 249 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 250 |\u001b[39m \u001b[90m// The XML shouldn't contain formatting newlines and indentation\u001b[39m\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 251 |\u001b[39m expect(result\u001b[33m.\u001b[39msplit(\u001b[32m'\\n'\u001b[39m)\u001b[33m.\u001b[39mlength)\u001b[33m.\u001b[39mtoBe(\u001b[35m1\u001b[39m)\u001b[33m;\u001b[39m \u001b[90m// Only the XML declaration might be on its own line\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 252 |\u001b[39m expect(result)\u001b[33m.\u001b[39mnot\u001b[33m.\u001b[39mtoContain(\u001b[32m' '\u001b[39m)\u001b[33m;\u001b[39m \u001b[90m// No indentation\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 253 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 254 |\u001b[39m \u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/JSONToXML.test.ts\u001b[39m\u001b[0m\u001b[2m:251:41)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mJSONToXML › configuration tests › should use custom property names when configured\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\n Expected substring: \u001b[32m\"Test\"\u001b[39m\n Received string: \u001b[31m\" Test \"\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 314 |\u001b[39m \u001b[36mconst\u001b[39m result \u001b[33m=\u001b[39m normalizeXML(customJsonToXML\u001b[33m.\u001b[39mserialize(json))\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 315 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 316 |\u001b[39m expect(result)\u001b[33m.\u001b[39mtoContain(\u001b[32m'Test'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 317 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 318 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 319 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/JSONToXML.test.ts\u001b[39m\u001b[0m\u001b[2m:316:22)\u001b[22m\u001b[2m\u001b[22m\n","testResults":[{"ancestorTitles":["JSONToXML","serialize"],"duration":3,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\nExpected substring: \u001b[32m\"Test\"\u001b[39m\nReceived string: \u001b[31m\" Test \"\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:43:22)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML serialize should convert a simple JSON object to XML","status":"failed","title":"should convert a simple JSON object to XML"},{"ancestorTitles":["JSONToXML","serialize"],"duration":0,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoMatch\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected pattern: \u001b[32m/^<\\?xml version=\"1\\.0\" encoding=\"UTF-8\"\\?>/\u001b[39m\nReceived string: \u001b[31m\" Test \"\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:51:22)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML serialize should include XML declaration when enabled","status":"failed","title":"should include XML declaration when enabled"},{"ancestorTitles":["JSONToXML","serialize"],"duration":0,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\nExpected substring: \u001b[32m\"Test\"\u001b[39m\nReceived string: \u001b[31m\" Test \"\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:71:22)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML serialize should handle attributes","status":"failed","title":"should handle attributes"},{"ancestorTitles":["JSONToXML","serialize"],"duration":0,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\nExpected substring: \u001b[32m\" Test
\"\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:93:22)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML serialize should handle namespaces when enabled","status":"failed","title":"should handle namespaces when enabled"},{"ancestorTitles":["JSONToXML","serialize"],"duration":0,"failureMessages":[],"fullName":"JSONToXML serialize should handle CDATA sections","status":"passed","title":"should handle CDATA sections"},{"ancestorTitles":["JSONToXML","serialize"],"duration":1,"failureMessages":[],"fullName":"JSONToXML serialize should handle comments when enabled","status":"passed","title":"should handle comments when enabled"},{"ancestorTitles":["JSONToXML","serialize"],"duration":0,"failureMessages":[],"fullName":"JSONToXML serialize should handle processing instructions when enabled","status":"passed","title":"should handle processing instructions when enabled"},{"ancestorTitles":["JSONToXML","serialize"],"duration":1,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\nExpected substring: \u001b[32m\"Child Text\"\u001b[39m\nReceived string: \u001b[31m\" Child Text \"\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:181:22)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML serialize should handle nested elements","status":"failed","title":"should handle nested elements"},{"ancestorTitles":["JSONToXML","serialize"],"duration":1,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\nExpected substring: \u001b[32m\"The Great Gatsby\"\u001b[39m\nReceived string: \u001b[31m\" The Great Gatsby F. Scott Fitzgerald 1925 that should be preserved]]>\"\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:205:25)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML serialize should work with the XMLToJSON parser in a round-trip","status":"failed","title":"should work with the XMLToJSON parser in a round-trip"},{"ancestorTitles":["JSONToXML","configuration tests"],"duration":1,"failureMessages":[],"fullName":"JSONToXML configuration tests should not include XML declaration when disabled","status":"passed","title":"should not include XML declaration when disabled"},{"ancestorTitles":["JSONToXML","configuration tests"],"duration":0,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m1\u001b[39m\nReceived: \u001b[31m2\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:251:41)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML configuration tests should not format XML (pretty print) when disabled","status":"failed","title":"should not format XML (pretty print) when disabled"},{"ancestorTitles":["JSONToXML","configuration tests"],"duration":0,"failureMessages":[],"fullName":"JSONToXML configuration tests should not include namespaces when disabled","status":"passed","title":"should not include namespaces when disabled"},{"ancestorTitles":["JSONToXML","configuration tests"],"duration":0,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoContain\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // indexOf\u001b[22m\n\nExpected substring: \u001b[32m\"Test\"\u001b[39m\nReceived string: \u001b[31m\" Test \"\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/JSONToXML.test.ts:316:22)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"JSONToXML configuration tests should use custom property names when configured","status":"failed","title":"should use custom property names when configured"}]},{"numFailingTests":6,"numPassingTests":6,"numPendingTests":0,"numTodoTests":0,"perfStats":{"end":1745548555520,"runtime":29,"slow":false,"start":1745548555491},"testFilePath":"/Users/summersw/Projects/git/xmlToJSON/test/unit/core/XMLToJSON.test.ts","failureMessage":"\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mXMLToJSON › parse › should convert a simple XML string to JSON\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m, \u001b[22m\u001b[32mvalue\u001b[39m\u001b[2m)\u001b[22m\n\n Expected path: \u001b[32m\"$val\"\u001b[39m\n Received path: \u001b[31m[]\u001b[39m\n\n Expected value: \u001b[32m\"Test\"\u001b[39m\n Received value: \u001b[31m{\"$children\": [{\"$val\": \"Test\"}]}\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 23 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot)\u001b[33m.\u001b[39mtoHaveProperty(testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 24 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren][\u001b[35m0\u001b[39m])\u001b[33m.\u001b[39mtoHaveProperty(\u001b[32m'item'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 25 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren][\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mitem)\u001b[33m.\u001b[39mtoHaveProperty(testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mvalue\u001b[33m,\u001b[39m \u001b[32m'Test'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 26 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 27 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 28 |\u001b[39m it(\u001b[32m'should handle XML attributes'\u001b[39m\u001b[33m,\u001b[39m () \u001b[33m=>\u001b[39m {\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/XMLToJSON.test.ts\u001b[39m\u001b[0m\u001b[2m:25:66)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mXMLToJSON › parse › should handle namespaces when enabled\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m)\u001b[22m\n\n Expected path: \u001b[32m\"$ns\"\u001b[39m\n Received path: \u001b[31m[]\u001b[39m\n\n Received value: \u001b[31m{\"$attr\": [{\"ns\": {\"$ns\": \"http://www.w3.org/2000/xmlns/\", \"$pre\": \"xmlns\", \"$val\": \"http://example.org\"}}], \"$children\": [{\"item\": {\"$children\": [{\"$val\": \"Test\"}], \"$ns\": \"http://example.org\", \"$pre\": \"ns\"}}]}\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 44 |\u001b[39m \u001b[36mconst\u001b[39m result \u001b[33m=\u001b[39m xmlToJSON\u001b[33m.\u001b[39mparse(xml)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 45 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 46 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot)\u001b[33m.\u001b[39mtoHaveProperty(testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mnamespace)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 47 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren][\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mitem)\u001b[33m.\u001b[39mtoHaveProperty(testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mnamespace\u001b[33m,\u001b[39m \u001b[32m'http://example.org'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 48 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren][\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mitem)\u001b[33m.\u001b[39mtoHaveProperty(testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mprefix\u001b[33m,\u001b[39m \u001b[32m'ns'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 49 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/XMLToJSON.test.ts\u001b[39m\u001b[0m\u001b[2m:46:27)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mXMLToJSON › parse › should handle nested elements\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m, \u001b[22m\u001b[32mvalue\u001b[39m\u001b[2m)\u001b[22m\n\n Expected path: \u001b[32m\"$val\"\u001b[39m\n Received path: \u001b[31m[]\u001b[39m\n\n Expected value: \u001b[32m\"Child Text\"\u001b[39m\n Received value: \u001b[31m{\"$children\": [{\"$val\": \"Child Text\"}]}\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 87 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 88 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren][\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mparent[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren][\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mchild)\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 89 |\u001b[39m \u001b[33m.\u001b[39mtoHaveProperty(testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mvalue\u001b[33m,\u001b[39m \u001b[32m'Child Text'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 90 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 91 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 92 |\u001b[39m it(\u001b[32m'should handle empty elements'\u001b[39m\u001b[33m,\u001b[39m () \u001b[33m=>\u001b[39m {\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/XMLToJSON.test.ts\u001b[39m\u001b[0m\u001b[2m:89:10)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mXMLToJSON › parse › should handle empty elements\u001b[39m\u001b[22m\n\n TypeError: Cannot read properties of undefined (reading 'find')\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 95 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 96 |\u001b[39m \u001b[36mconst\u001b[39m children \u001b[33m=\u001b[39m result\u001b[33m.\u001b[39mroot[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren]\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 97 |\u001b[39m \u001b[36mconst\u001b[39m emptyElement \u001b[33m=\u001b[39m children\u001b[33m.\u001b[39mfind((child\u001b[33m:\u001b[39m \u001b[33mRecord\u001b[39m\u001b[33m<\u001b[39m\u001b[33mstring\u001b[39m\u001b[33m,\u001b[39m any\u001b[33m>\u001b[39m) \u001b[33m=>\u001b[39m child\u001b[33m.\u001b[39mempty)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 98 |\u001b[39m \u001b[36mconst\u001b[39m selfClosingElement \u001b[33m=\u001b[39m children\u001b[33m.\u001b[39mfind((child\u001b[33m:\u001b[39m \u001b[33mRecord\u001b[39m\u001b[33m<\u001b[39m\u001b[33mstring\u001b[39m\u001b[33m,\u001b[39m any\u001b[33m>\u001b[39m) \u001b[33m=>\u001b[39m child[\u001b[32m'self-closing'\u001b[39m])\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 99 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[90m 100 |\u001b[39m expect(emptyElement)\u001b[33m.\u001b[39mtoBeDefined()\u001b[33m;\u001b[39m\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/XMLToJSON.test.ts\u001b[39m\u001b[0m\u001b[2m:97:37)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mXMLToJSON › configuration tests › should not preserve CDATA sections when disabled\u001b[39m\u001b[22m\n\n TypeError: Cannot read properties of undefined (reading '0')\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 140 |\u001b[39m \u001b[36mconst\u001b[39m result \u001b[33m=\u001b[39m customXmlToJSON\u001b[33m.\u001b[39mparse(xml)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 141 |\u001b[39m \u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 142 |\u001b[39m \u001b[36mconst\u001b[39m hasCDATA \u001b[33m=\u001b[39m result\u001b[33m.\u001b[39mroot[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren][\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mitem[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mchildren]\u001b[33m?\u001b[39m\u001b[33m.\u001b[39msome(\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 143 |\u001b[39m (child\u001b[33m:\u001b[39m \u001b[33mRecord\u001b[39m\u001b[33m<\u001b[39m\u001b[33mstring\u001b[39m\u001b[33m,\u001b[39m any\u001b[33m>\u001b[39m) \u001b[33m=>\u001b[39m child[testConfig\u001b[33m.\u001b[39mpropNames\u001b[33m.\u001b[39mcdata]\u001b[22m\n\u001b[2m \u001b[90m 144 |\u001b[39m )\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 145 |\u001b[39m \u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/XMLToJSON.test.ts\u001b[39m\u001b[0m\u001b[2m:142:66)\u001b[22m\u001b[2m\u001b[22m\n\n\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mXMLToJSON › configuration tests › should use custom property names when configured\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m, \u001b[22m\u001b[32mvalue\u001b[39m\u001b[2m)\u001b[22m\n\n Expected path: \u001b[32m\"_val\"\u001b[39m\n Received path: \u001b[31m[]\u001b[39m\n\n Expected value: \u001b[32m\"Test\"\u001b[39m\n Received value: \u001b[31m{\"_attrs\": [{\"id\": {\"_val\": \"123\"}}], \"_children\": [{\"_val\": \"Test\"}]}\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 168 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot)\u001b[33m.\u001b[39mtoHaveProperty(\u001b[32m'_children'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 169 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot\u001b[33m.\u001b[39m_children[\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mitem)\u001b[33m.\u001b[39mtoHaveProperty(\u001b[32m'_attrs'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 170 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot\u001b[33m.\u001b[39m_children[\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mitem)\u001b[33m.\u001b[39mtoHaveProperty(\u001b[32m'_val'\u001b[39m\u001b[33m,\u001b[39m \u001b[32m'Test'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 171 |\u001b[39m expect(result\u001b[33m.\u001b[39mroot\u001b[33m.\u001b[39m_children[\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mitem\u001b[33m.\u001b[39m_attrs[\u001b[35m0\u001b[39m]\u001b[33m.\u001b[39mid)\u001b[33m.\u001b[39mtoHaveProperty(\u001b[32m'_val'\u001b[39m\u001b[33m,\u001b[39m \u001b[32m'123'\u001b[39m)\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 172 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 173 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object. (\u001b[22m\u001b[2m\u001b[0m\u001b[36mtest/unit/core/XMLToJSON.test.ts\u001b[39m\u001b[0m\u001b[2m:170:45)\u001b[22m\u001b[2m\u001b[22m\n","testResults":[{"ancestorTitles":["XMLToJSON","parse"],"duration":1,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m, \u001b[22m\u001b[32mvalue\u001b[39m\u001b[2m)\u001b[22m\n\nExpected path: \u001b[32m\"$val\"\u001b[39m\nReceived path: \u001b[31m[]\u001b[39m\n\nExpected value: \u001b[32m\"Test\"\u001b[39m\nReceived value: \u001b[31m{\"$children\": [{\"$val\": \"Test\"}]}\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/XMLToJSON.test.ts:25:66)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"XMLToJSON parse should convert a simple XML string to JSON","status":"failed","title":"should convert a simple XML string to JSON"},{"ancestorTitles":["XMLToJSON","parse"],"duration":1,"failureMessages":[],"fullName":"XMLToJSON parse should handle XML attributes","status":"passed","title":"should handle XML attributes"},{"ancestorTitles":["XMLToJSON","parse"],"duration":0,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m)\u001b[22m\n\nExpected path: \u001b[32m\"$ns\"\u001b[39m\nReceived path: \u001b[31m[]\u001b[39m\n\nReceived value: \u001b[31m{\"$attr\": [{\"ns\": {\"$ns\": \"http://www.w3.org/2000/xmlns/\", \"$pre\": \"xmlns\", \"$val\": \"http://example.org\"}}], \"$children\": [{\"item\": {\"$children\": [{\"$val\": \"Test\"}], \"$ns\": \"http://example.org\", \"$pre\": \"ns\"}}]}\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/XMLToJSON.test.ts:46:27)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"XMLToJSON parse should handle namespaces when enabled","status":"failed","title":"should handle namespaces when enabled"},{"ancestorTitles":["XMLToJSON","parse"],"duration":1,"failureMessages":[],"fullName":"XMLToJSON parse should handle CDATA sections","status":"passed","title":"should handle CDATA sections"},{"ancestorTitles":["XMLToJSON","parse"],"duration":0,"failureMessages":[],"fullName":"XMLToJSON parse should handle comments when enabled","status":"passed","title":"should handle comments when enabled"},{"ancestorTitles":["XMLToJSON","parse"],"duration":0,"failureMessages":[],"fullName":"XMLToJSON parse should handle processing instructions when enabled","status":"passed","title":"should handle processing instructions when enabled"},{"ancestorTitles":["XMLToJSON","parse"],"duration":1,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m, \u001b[22m\u001b[32mvalue\u001b[39m\u001b[2m)\u001b[22m\n\nExpected path: \u001b[32m\"$val\"\u001b[39m\nReceived path: \u001b[31m[]\u001b[39m\n\nExpected value: \u001b[32m\"Child Text\"\u001b[39m\nReceived value: \u001b[31m{\"$children\": [{\"$val\": \"Child Text\"}]}\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/XMLToJSON.test.ts:89:10)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"XMLToJSON parse should handle nested elements","status":"failed","title":"should handle nested elements"},{"ancestorTitles":["XMLToJSON","parse"],"duration":0,"failureMessages":["TypeError: Cannot read properties of undefined (reading 'find')\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/XMLToJSON.test.ts:97:37)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"XMLToJSON parse should handle empty elements","status":"failed","title":"should handle empty elements"},{"ancestorTitles":["XMLToJSON","configuration tests"],"duration":1,"failureMessages":[],"fullName":"XMLToJSON configuration tests should not preserve namespaces when disabled","status":"passed","title":"should not preserve namespaces when disabled"},{"ancestorTitles":["XMLToJSON","configuration tests"],"duration":0,"failureMessages":[],"fullName":"XMLToJSON configuration tests should not preserve comments when disabled","status":"passed","title":"should not preserve comments when disabled"},{"ancestorTitles":["XMLToJSON","configuration tests"],"duration":0,"failureMessages":["TypeError: Cannot read properties of undefined (reading '0')\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/XMLToJSON.test.ts:142:66)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"XMLToJSON configuration tests should not preserve CDATA sections when disabled","status":"failed","title":"should not preserve CDATA sections when disabled"},{"ancestorTitles":["XMLToJSON","configuration tests"],"duration":1,"failureMessages":["Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveProperty\u001b[2m(\u001b[22m\u001b[32mpath\u001b[39m\u001b[2m, \u001b[22m\u001b[32mvalue\u001b[39m\u001b[2m)\u001b[22m\n\nExpected path: \u001b[32m\"_val\"\u001b[39m\nReceived path: \u001b[31m[]\u001b[39m\n\nExpected value: \u001b[32m\"Test\"\u001b[39m\nReceived value: \u001b[31m{\"_attrs\": [{\"id\": {\"_val\": \"123\"}}], \"_children\": [{\"_val\": \"Test\"}]}\u001b[39m\n at Object. (/Users/summersw/Projects/git/xmlToJSON/test/unit/core/XMLToJSON.test.ts:170:45)\n at Promise.then.completed (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at _runTestsForDescribeBlock (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:121:9)\n at run (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-runner/build/runTest.js:444:34)"],"fullName":"XMLToJSON configuration tests should use custom property names when configured","status":"failed","title":"should use custom property names when configured"}]},{"numFailingTests":0,"numPassingTests":20,"numPendingTests":0,"numTodoTests":0,"perfStats":{"end":1745548555544,"runtime":19,"slow":false,"start":1745548555525},"testFilePath":"/Users/summersw/Projects/git/xmlToJSON/test/unit/core/utils/XMLUtil.test.ts","failureMessage":null,"testResults":[{"ancestorTitles":["XMLUtil","prettyPrintXml"],"duration":1,"failureMessages":[],"fullName":"XMLUtil prettyPrintXml should format XML with proper indentation","status":"passed","title":"should format XML with proper indentation"},{"ancestorTitles":["XMLUtil","prettyPrintXml"],"duration":0,"failureMessages":[],"fullName":"XMLUtil prettyPrintXml should handle XML with attributes","status":"passed","title":"should handle XML with attributes"},{"ancestorTitles":["XMLUtil","prettyPrintXml"],"duration":0,"failureMessages":[],"fullName":"XMLUtil prettyPrintXml should handle empty elements correctly","status":"passed","title":"should handle empty elements correctly"},{"ancestorTitles":["XMLUtil","prettyPrintXml"],"duration":1,"failureMessages":[],"fullName":"XMLUtil prettyPrintXml should respect custom indentation","status":"passed","title":"should respect custom indentation"},{"ancestorTitles":["XMLUtil","validateXML"],"duration":0,"failureMessages":[],"fullName":"XMLUtil validateXML should return true for valid XML","status":"passed","title":"should return true for valid XML"},{"ancestorTitles":["XMLUtil","validateXML"],"duration":0,"failureMessages":[],"fullName":"XMLUtil validateXML should return false for XML with unclosed tags","status":"passed","title":"should return false for XML with unclosed tags"},{"ancestorTitles":["XMLUtil","validateXML"],"duration":0,"failureMessages":[],"fullName":"XMLUtil validateXML should return false for XML with malformed attributes","status":"passed","title":"should return false for XML with malformed attributes"},{"ancestorTitles":["XMLUtil","validateXML"],"duration":0,"failureMessages":[],"fullName":"XMLUtil validateXML should return false for non-XML content","status":"passed","title":"should return false for non-XML content"},{"ancestorTitles":["XMLUtil","ensureXMLDeclaration"],"duration":0,"failureMessages":[],"fullName":"XMLUtil ensureXMLDeclaration should add XML declaration if missing","status":"passed","title":"should add XML declaration if missing"},{"ancestorTitles":["XMLUtil","ensureXMLDeclaration"],"duration":0,"failureMessages":[],"fullName":"XMLUtil ensureXMLDeclaration should not add XML declaration if already present","status":"passed","title":"should not add XML declaration if already present"},{"ancestorTitles":["XMLUtil","ensureXMLDeclaration"],"duration":1,"failureMessages":[],"fullName":"XMLUtil ensureXMLDeclaration should handle XML declaration with different attributes","status":"passed","title":"should handle XML declaration with different attributes"},{"ancestorTitles":["XMLUtil","escapeXML & unescapeXML"],"duration":0,"failureMessages":[],"fullName":"XMLUtil escapeXML & unescapeXML should escape special XML characters","status":"passed","title":"should escape special XML characters"},{"ancestorTitles":["XMLUtil","escapeXML & unescapeXML"],"duration":0,"failureMessages":[],"fullName":"XMLUtil escapeXML & unescapeXML should unescape XML entities","status":"passed","title":"should unescape XML entities"},{"ancestorTitles":["XMLUtil","escapeXML & unescapeXML"],"duration":0,"failureMessages":[],"fullName":"XMLUtil escapeXML & unescapeXML should handle round-trip escape/unescape correctly","status":"passed","title":"should handle round-trip escape/unescape correctly"},{"ancestorTitles":["XMLUtil","extractPrefix & extractLocalName"],"duration":0,"failureMessages":[],"fullName":"XMLUtil extractPrefix & extractLocalName should extract namespace prefix from qualified name","status":"passed","title":"should extract namespace prefix from qualified name"},{"ancestorTitles":["XMLUtil","extractPrefix & extractLocalName"],"duration":0,"failureMessages":[],"fullName":"XMLUtil extractPrefix & extractLocalName should return null for names without prefix","status":"passed","title":"should return null for names without prefix"},{"ancestorTitles":["XMLUtil","extractPrefix & extractLocalName"],"duration":0,"failureMessages":[],"fullName":"XMLUtil extractPrefix & extractLocalName should extract local name from qualified name","status":"passed","title":"should extract local name from qualified name"},{"ancestorTitles":["XMLUtil","extractPrefix & extractLocalName"],"duration":1,"failureMessages":[],"fullName":"XMLUtil extractPrefix & extractLocalName should return the name itself for names without prefix","status":"passed","title":"should return the name itself for names without prefix"},{"ancestorTitles":["XMLUtil","createQualifiedName"],"duration":0,"failureMessages":[],"fullName":"XMLUtil createQualifiedName should create qualified name with prefix","status":"passed","title":"should create qualified name with prefix"},{"ancestorTitles":["XMLUtil","createQualifiedName"],"duration":0,"failureMessages":[],"fullName":"XMLUtil createQualifiedName should return only local name when prefix is null","status":"passed","title":"should return only local name when prefix is null"}]},{"numFailingTests":0,"numPassingTests":22,"numPendingTests":0,"numTodoTests":0,"perfStats":{"end":1745548555567,"runtime":18,"slow":false,"start":1745548555549},"testFilePath":"/Users/summersw/Projects/git/xmlToJSON/test/unit/core/utils/JSONUtil.test.ts","failureMessage":null,"testResults":[{"ancestorTitles":["JSONUtil","getPath"],"duration":0,"failureMessages":[],"fullName":"JSONUtil getPath should retrieve values using dot notation","status":"passed","title":"should retrieve values using dot notation"},{"ancestorTitles":["JSONUtil","getPath"],"duration":0,"failureMessages":[],"fullName":"JSONUtil getPath should traverse arrays automatically","status":"passed","title":"should traverse arrays automatically"},{"ancestorTitles":["JSONUtil","getPath"],"duration":0,"failureMessages":[],"fullName":"JSONUtil getPath should return fallback value when path does not exist","status":"passed","title":"should return fallback value when path does not exist"},{"ancestorTitles":["JSONUtil","getPath"],"duration":0,"failureMessages":[],"fullName":"JSONUtil getPath should handle XML-like JSON structures","status":"passed","title":"should handle XML-like JSON structures"},{"ancestorTitles":["JSONUtil","getPath"],"duration":0,"failureMessages":[],"fullName":"JSONUtil getPath should collapse singleton arrays","status":"passed","title":"should collapse singleton arrays"},{"ancestorTitles":["JSONUtil","fromJSONObject"],"duration":1,"failureMessages":[],"fullName":"JSONUtil fromJSONObject should convert a plain JSON object to XML-like JSON structure","status":"passed","title":"should convert a plain JSON object to XML-like JSON structure"},{"ancestorTitles":["JSONUtil","fromJSONObject"],"duration":0,"failureMessages":[],"fullName":"JSONUtil fromJSONObject should wrap result in a root element if provided","status":"passed","title":"should wrap result in a root element if provided"},{"ancestorTitles":["JSONUtil","fromJSONObject"],"duration":0,"failureMessages":[],"fullName":"JSONUtil fromJSONObject should handle arrays correctly","status":"passed","title":"should handle arrays correctly"},{"ancestorTitles":["JSONUtil","fromJSONObject"],"duration":0,"failureMessages":[],"fullName":"JSONUtil fromJSONObject should handle complex root configuration","status":"passed","title":"should handle complex root configuration"},{"ancestorTitles":["JSONUtil","isEmpty"],"duration":0,"failureMessages":[],"fullName":"JSONUtil isEmpty should return true for null and undefined","status":"passed","title":"should return true for null and undefined"},{"ancestorTitles":["JSONUtil","isEmpty"],"duration":0,"failureMessages":[],"fullName":"JSONUtil isEmpty should return true for empty arrays","status":"passed","title":"should return true for empty arrays"},{"ancestorTitles":["JSONUtil","isEmpty"],"duration":0,"failureMessages":[],"fullName":"JSONUtil isEmpty should return true for empty objects","status":"passed","title":"should return true for empty objects"},{"ancestorTitles":["JSONUtil","isEmpty"],"duration":0,"failureMessages":[],"fullName":"JSONUtil isEmpty should return false for non-empty arrays","status":"passed","title":"should return false for non-empty arrays"},{"ancestorTitles":["JSONUtil","isEmpty"],"duration":0,"failureMessages":[],"fullName":"JSONUtil isEmpty should return false for non-empty objects","status":"passed","title":"should return false for non-empty objects"},{"ancestorTitles":["JSONUtil","isEmpty"],"duration":0,"failureMessages":[],"fullName":"JSONUtil isEmpty should return false for primitive values","status":"passed","title":"should return false for primitive values"},{"ancestorTitles":["JSONUtil","safeStringify"],"duration":0,"failureMessages":[],"fullName":"JSONUtil safeStringify should stringify valid JSON objects","status":"passed","title":"should stringify valid JSON objects"},{"ancestorTitles":["JSONUtil","safeStringify"],"duration":0,"failureMessages":[],"fullName":"JSONUtil safeStringify should handle circular references gracefully","status":"passed","title":"should handle circular references gracefully"},{"ancestorTitles":["JSONUtil","safeStringify"],"duration":0,"failureMessages":[],"fullName":"JSONUtil safeStringify should respect custom indent","status":"passed","title":"should respect custom indent"},{"ancestorTitles":["JSONUtil","deepClone and deepMerge"],"duration":1,"failureMessages":[],"fullName":"JSONUtil deepClone and deepMerge should create a deep clone of an object","status":"passed","title":"should create a deep clone of an object"},{"ancestorTitles":["JSONUtil","deepClone and deepMerge"],"duration":0,"failureMessages":[],"fullName":"JSONUtil deepClone and deepMerge should deep merge two objects","status":"passed","title":"should deep merge two objects"},{"ancestorTitles":["JSONUtil","deepClone and deepMerge"],"duration":0,"failureMessages":[],"fullName":"JSONUtil deepClone and deepMerge should handle arrays during merge","status":"passed","title":"should handle arrays during merge"},{"ancestorTitles":["JSONUtil","deepClone and deepMerge"],"duration":0,"failureMessages":[],"fullName":"JSONUtil deepClone and deepMerge should handle null and undefined values","status":"passed","title":"should handle null and undefined values"}]},{"numFailingTests":0,"numPassingTests":16,"numPendingTests":0,"numTodoTests":0,"perfStats":{"end":1745548555589,"runtime":17,"slow":false,"start":1745548555572},"testFilePath":"/Users/summersw/Projects/git/xmlToJSON/test/unit/core/DOMAdapter.test.ts","failureMessage":null,"testResults":[{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create a DOM parser","status":"passed","title":"should create a DOM parser"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create an XML serializer","status":"passed","title":"should create an XML serializer"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should parse XML strings","status":"passed","title":"should parse XML strings"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should serialize DOM nodes to XML strings","status":"passed","title":"should serialize DOM nodes to XML strings"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create new documents","status":"passed","title":"should create new documents"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":1,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create elements","status":"passed","title":"should create elements"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create elements with namespaces","status":"passed","title":"should create elements with namespaces"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create text nodes","status":"passed","title":"should create text nodes"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create CDATA sections","status":"passed","title":"should create CDATA sections"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create comments","status":"passed","title":"should create comments"},{"ancestorTitles":["DOMAdapter","DOM methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter DOM methods should create processing instructions","status":"passed","title":"should create processing instructions"},{"ancestorTitles":["DOMAdapter","Helper methods"],"duration":1,"failureMessages":[],"fullName":"DOMAdapter Helper methods should set namespaced attributes","status":"passed","title":"should set namespaced attributes"},{"ancestorTitles":["DOMAdapter","Helper methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter Helper methods should set regular attributes when namespace is null","status":"passed","title":"should set regular attributes when namespace is null"},{"ancestorTitles":["DOMAdapter","Helper methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter Helper methods should detect DOM nodes","status":"passed","title":"should detect DOM nodes"},{"ancestorTitles":["DOMAdapter","Helper methods"],"duration":0,"failureMessages":[],"fullName":"DOMAdapter Helper methods should get node type names","status":"passed","title":"should get node type names"},{"ancestorTitles":["DOMAdapter","Helper methods"],"duration":1,"failureMessages":[],"fullName":"DOMAdapter Helper methods should get all node attributes as an object","status":"passed","title":"should get all node attributes as an object"}]},{"numFailingTests":0,"numPassingTests":0,"numPendingTests":0,"numTodoTests":0,"perfStats":{"end":0,"runtime":0,"slow":false,"start":0},"testFilePath":"/Users/summersw/Projects/git/xmlToJSON/test/utils/testUtils.ts","failureMessage":" \u001b[1m● \u001b[22mTest suite failed to run\n\n Your test suite must contain at least one test.\n\n \u001b[2mat onResult (\u001b[22mnode_modules/@jest/core/build/TestScheduler.js\u001b[2m:133:18)\u001b[22m\n \u001b[2mat \u001b[22mnode_modules/@jest/core/build/TestScheduler.js\u001b[2m:254:19\u001b[22m\n \u001b[2mat \u001b[22mnode_modules/emittery/index.js\u001b[2m:363:13\u001b[22m\n at Array.map ()\n \u001b[2mat Emittery.emit (\u001b[22mnode_modules/emittery/index.js\u001b[2m:361:23)\u001b[22m\n","testResults":[]},{"numFailingTests":0,"numPassingTests":0,"numPendingTests":0,"numTodoTests":0,"perfStats":{"end":0,"runtime":0,"slow":false,"start":0},"testFilePath":"/Users/summersw/Projects/git/xmlToJSON/test/jest.setup.ts","failureMessage":" \u001b[1m● \u001b[22mTest suite failed to run\n\n Your test suite must contain at least one test.\n\n \u001b[2mat onResult (\u001b[22mnode_modules/@jest/core/build/TestScheduler.js\u001b[2m:133:18)\u001b[22m\n \u001b[2mat \u001b[22mnode_modules/@jest/core/build/TestScheduler.js\u001b[2m:254:19\u001b[22m\n \u001b[2mat \u001b[22mnode_modules/emittery/index.js\u001b[2m:363:13\u001b[22m\n at Array.map ()\n \u001b[2mat Emittery.emit (\u001b[22mnode_modules/emittery/index.js\u001b[2m:361:23)\u001b[22m\n","testResults":[]}],"config":{"bail":0,"changedFilesWithAncestor":false,"ci":false,"collectCoverage":false,"collectCoverageFrom":["src/**/*.ts","!src/**/*.d.ts","!src/**/index.ts"],"coverageDirectory":"/Users/summersw/Projects/git/xmlToJSON/coverage","coverageProvider":"babel","coverageReporters":["json","text","lcov","clover"],"detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"expand":false,"findRelatedTests":false,"forceExit":false,"json":false,"lastCommit":false,"listTests":false,"logHeapUsage":false,"maxConcurrency":5,"maxWorkers":7,"noStackTrace":false,"nonFlagArgs":[],"notify":false,"notifyMode":"failure-change","onlyChanged":false,"onlyFailures":false,"openHandlesTimeout":1000,"passWithNoTests":false,"projects":[],"reporters":[["default",{}],["/Users/summersw/Projects/git/xmlToJSON/node_modules/jest-html-reporters/index.js",{"publicPath":"reports/","filename":"test-report.html","expand":false,"includeFailureMsg":true,"includeConsoleLog":true}]],"rootDir":"/Users/summersw/Projects/git/xmlToJSON","runTestsByPath":false,"seed":1416794856,"skipFilter":false,"snapshotFormat":{"escapeString":false,"printBasicPrototype":false},"testFailureExitCode":1,"testPathPattern":"","testSequencer":"/Users/summersw/Projects/git/xmlToJSON/node_modules/@jest/test-sequencer/build/index.js","updateSnapshot":"new","useStderr":false,"watch":false,"watchAll":false,"watchman":true,"workerThreads":false},"endTime":1745548555624,"_reporterOptions":{"publicPath":"reports/","filename":"test-report.html","expand":false,"pageTitle":"","hideIcon":false,"testCommand":"","openReport":false,"failureMessageOnly":0,"enableMergeData":false,"dataMergeLevel":1,"inlineSource":false,"urlForTestFiles":"","darkTheme":false,"includeConsoleLog":true,"stripSkippedTest":false,"includeFailureMsg":true},"logInfoMapping":{},"attachInfos":{}}) \ No newline at end of file diff --git a/reports/test-report.html b/reports/test-report.html new file mode 100644 index 0000000..bb4210c --- /dev/null +++ b/reports/test-report.html @@ -0,0 +1 @@ +Report
\ No newline at end of file From 22b73f4225dcd465965fa4df83bb17edb4a6ad00 Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 09:54:37 -0500 Subject: [PATCH 26/38] updated browser example with getPath demo --- examples/browser-example.html | 136 ++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/examples/browser-example.html b/examples/browser-example.html index c98eef7..6284e43 100644 --- a/examples/browser-example.html +++ b/examples/browser-example.html @@ -78,6 +78,62 @@ width: 60px; padding: 4px; } + + .path-container { + margin: 20px 0; + padding: 15px; + background-color: #f9f9f9; + border-radius: 4px; + } + + .input-group { + display: flex; + align-items: center; + margin-bottom: 15px; + } + + .input-group label { + margin-right: 10px; + font-weight: bold; + } + + .path-input { + flex: 1; + padding: 8px; + border: 1px solid #ccc; + border-radius: 4px; + font-family: monospace; + } + + .output-group { + display: flex; + flex-direction: column; + } + + .output-group label { + margin-bottom: 5px; + font-weight: bold; + } + + .output-group textarea { + width: 100%; + height: 120px; + padding: 10px; + border: 1px solid #ccc; + border-radius: 4px; + font-family: monospace; + resize: vertical; + background-color: #f5f5f5; + } + + .section { + margin: 30px 0; + } + + .btn { + margin-left: 10px; + } + @@ -254,6 +310,30 @@

JSON

+
+

Path Navigation

+

Use dot notation to navigate the JSON structure and extract specific values

+ +
+
+ + + + +
+ +
+ + +
+
+
+ @@ -404,6 +484,62 @@

JSON

xmlToJsonBtn.click(); }, 100); }); + + + // DOM Elements for path navigation + const pathInput = document.getElementById("pathInput"); + const pathResult = document.getElementById("pathResult"); + const getPathBtn = document.getElementById("getPathBtn"); + const clearPathBtn = document.getElementById("clearPathBtn"); + + // Get Path functionality + getPathBtn.addEventListener("click", () => { + try { + // First make sure we have a JSON object to navigate + if (!jsonOutput.value) { + throw new Error("Please convert XML to JSON first before using getPath"); + } + + const jsonObj = JSON.parse(jsonOutput.value); + const path = pathInput.value.trim(); + + if (!path) { + throw new Error("Please enter a path to navigate"); + } + + // Check if XJX is a constructor function (class) or an object with a default property + const XJXClass = typeof XJX === "function" ? XJX : XJX.default || XJX.XJX || XJX; + + if (typeof XJXClass !== "function") { + throw new Error( + "XJX is not available as a constructor. Available as: " + + Object.keys(XJX).join(", ") + ); + } + + const converter = new XJXClass(getConfig()); + const result = converter.getPath(jsonObj, path); + + // Format the result for display + if (result === undefined) { + pathResult.value = "Path not found"; + } else if (typeof result === "object") { + pathResult.value = JSON.stringify(result, null, 2); + } else { + pathResult.value = String(result); + } + } catch (error) { + pathResult.value = `Error: ${error.message}`; + console.error("Error details:", error); + } + }); + + // Clear path navigation fields + clearPathBtn.addEventListener("click", () => { + pathInput.value = ""; + pathResult.value = ""; + }); + \ No newline at end of file From e6486a3f573136c4ee46af9648b3e3852a39a91d Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 10:11:58 -0500 Subject: [PATCH 27/38] added value transformer feature file renaming --- README.md | 6 +- src/XJX.ts | 69 +++++++++- src/core/DOMAdapter.ts | 2 +- .../{JSONToXML.ts => JsonToXmlConverter.ts} | 119 ++++++++++++++--- .../{XMLToJSON.ts => XmlToJsonConverter.ts} | 93 +++++++++++-- src/core/transforms/BooleanTransformer.ts | 101 ++++++++++++++ src/core/transforms/NumberTransformer.ts | 123 ++++++++++++++++++ .../transforms/StringReplaceTransformer.ts | 101 ++++++++++++++ src/core/transforms/TransformUtil.ts | 86 ++++++++++++ src/core/transforms/ValueTransformer.ts | 75 +++++++++++ src/core/transforms/index.ts | 16 +++ src/core/types/types.ts | 4 + src/core/utils/{JSONUtil.ts => JsonUtils.ts} | 0 src/core/utils/{XMLUtil.ts => XmlUtils.ts} | 2 +- src/index.ts | 25 +++- 15 files changed, 782 insertions(+), 40 deletions(-) rename src/core/{JSONToXML.ts => JsonToXmlConverter.ts} (64%) rename src/core/{XMLToJSON.ts => XmlToJsonConverter.ts} (72%) create mode 100644 src/core/transforms/BooleanTransformer.ts create mode 100644 src/core/transforms/NumberTransformer.ts create mode 100644 src/core/transforms/StringReplaceTransformer.ts create mode 100644 src/core/transforms/TransformUtil.ts create mode 100644 src/core/transforms/ValueTransformer.ts create mode 100644 src/core/transforms/index.ts rename src/core/utils/{JSONUtil.ts => JsonUtils.ts} (100%) rename src/core/utils/{XMLUtil.ts => XmlUtils.ts} (99%) diff --git a/README.md b/README.md index d306be3..c06f1e3 100644 --- a/README.md +++ b/README.md @@ -378,7 +378,7 @@ The main class for XML to JSON conversion. ```typescript constructor( - config?: Partial, + config?: Partial, customDOMImplementation?: DOMImplementation ) ``` @@ -407,12 +407,12 @@ Converts a JSON object to an XML string. Cleans up any resources, especially important when using JSDOM. -### Interface: XMLToJSONConfig +### Interface: Configuration Configuration interface for XMLToJSON. ```typescript -interface XMLToJSONConfig { +interface Configuration { // Features to preserve during transformation preserveNamespaces: boolean; preserveComments: boolean; diff --git a/src/XJX.ts b/src/XJX.ts index 013f574..6803c27 100644 --- a/src/XJX.ts +++ b/src/XJX.ts @@ -1,13 +1,17 @@ /** * XJX - Facade class for XML-JSON conversion operations */ -import { XMLToJSON } from "./core/XMLToJSON"; -import { JSONToXML } from "./core/JSONToXML"; +import { XMLToJSON } from "./core/XmlToJsonConverter"; +import { JSONToXML } from "./core/JsonToXmlConverter"; import { Configuration } from "./core/types/types"; import { DEFAULT_CONFIG } from "./core/config/config"; import { DOMAdapter } from "./core/DOMAdapter"; -import { XMLUtil } from "./core/utils/XMLUtil"; -import { JSONUtil } from "./core/utils/JSONUtil"; +import { XMLUtil } from "./core/utils/XmlUtils"; +import { JSONUtil } from "./core/utils/JsonUtils"; +import { ValueTransformer } from "./core/transforms/ValueTransformer"; +import { BooleanTransformer } from "./core/transforms/BooleanTransformer"; +import { NumberTransformer } from "./core/transforms/NumberTransformer"; +import { StringReplaceTransformer } from "./core/transforms/StringReplaceTransformer"; export class XJX { private config: Configuration; @@ -93,10 +97,65 @@ export class XJX { return this.xmlUtil.validateXML(xmlString); } + /** + * Add a value transformer to the configuration + * @param transformer Value transformer to add + * @returns This XJX instance for chaining + */ + public addTransformer(transformer: ValueTransformer): XJX { + if (!this.config.valueTransforms) { + this.config.valueTransforms = []; + } + this.config.valueTransforms.push(transformer); + return this; + } + + /** + * Removes all value transformers from the configuration + * @returns This XJX instance for chaining + */ + public clearTransformers(): XJX { + this.config.valueTransforms = []; + return this; + } + + /** + * Create a new boolean transformer and add it to the configuration + * @param options Options for the transformer + * @returns The created transformer instance + */ + public createBooleanTransformer(options = {}): BooleanTransformer { + const transformer = new BooleanTransformer(options); + this.addTransformer(transformer); + return transformer; + } + + /** + * Create a new number transformer and add it to the configuration + * @param options Options for the transformer + * @returns The created transformer instance + */ + public createNumberTransformer(options = {}): NumberTransformer { + const transformer = new NumberTransformer(options); + this.addTransformer(transformer); + return transformer; + } + + /** + * Create a new string replace transformer and add it to the configuration + * @param options Options for the transformer + * @returns The created transformer instance + */ + public createStringReplaceTransformer(options = {}): StringReplaceTransformer { + const transformer = new StringReplaceTransformer(options); + this.addTransformer(transformer); + return transformer; + } + /** * Clean up any resources */ public cleanup(): void { DOMAdapter.cleanup(); } -} +} \ No newline at end of file diff --git a/src/core/DOMAdapter.ts b/src/core/DOMAdapter.ts index fe1b798..c1a3b4b 100644 --- a/src/core/DOMAdapter.ts +++ b/src/core/DOMAdapter.ts @@ -1,7 +1,7 @@ /** * DOM Environment provider with unified interface for browser and Node.js */ -import { XMLToJSONError } from './types/errors'; +import { XMLToJSONError } from './types/Errors'; interface NodeTypes { ELEMENT_NODE: number; diff --git a/src/core/JSONToXML.ts b/src/core/JsonToXmlConverter.ts similarity index 64% rename from src/core/JSONToXML.ts rename to src/core/JsonToXmlConverter.ts index 7a34ca9..3935a37 100644 --- a/src/core/JSONToXML.ts +++ b/src/core/JsonToXmlConverter.ts @@ -2,9 +2,11 @@ * JSONToXML class for converting JSON to XML with consistent namespace handling */ import { Configuration } from "./types/types"; -import { XMLToJSONError } from "./types/errors"; +import { XMLToJSONError } from "./types/Errors"; import { DOMAdapter } from "./DOMAdapter"; -import { XMLUtil } from "./utils/XMLUtil"; +import { XMLUtil } from "./utils/XmlUtils"; +import { TransformUtil } from "./transforms/TransformUtil"; +import { TransformContext } from "./transforms/ValueTransformer"; /** * JSONToXML for converting JSON to XML @@ -12,6 +14,7 @@ import { XMLUtil } from "./utils/XMLUtil"; export class JSONToXML { private config: Configuration; private xmlUtil: XMLUtil; + private transformUtil: TransformUtil; /** * Constructor for JSONToXML @@ -20,6 +23,7 @@ export class JSONToXML { constructor(config: Configuration) { this.config = config; this.xmlUtil = new XMLUtil(this.config); + this.transformUtil = new TransformUtil(this.config); } /** @@ -70,17 +74,15 @@ export class JSONToXML { * Convert JSON object to DOM node * @param jsonObj JSON object to convert * @param doc Document for creating elements - * @returns DOM Element - */ - /** - * Convert JSON object to DOM node - * @param jsonObj JSON object to convert - * @param doc Document for creating elements + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the JSON object * @returns DOM Element */ private jsonToNode( jsonObj: Record, - doc: Document + doc: Document, + parentContext?: TransformContext, + path: string = "" ): Element | null { if (!jsonObj || typeof jsonObj !== "object") { return null; @@ -93,6 +95,9 @@ export class JSONToXML { } const nodeData = jsonObj[nodeName]; + + // Update the current path + const currentPath = path ? `${path}.${nodeName}` : nodeName; // Create element with namespace if available let element: Element; @@ -101,6 +106,19 @@ export class JSONToXML { const ns = nodeData[namespaceKey]; const prefix = nodeData[prefixKey]; + // Create context for this node + const context = this.transformUtil.createContext( + 'json-to-xml', + nodeName, + DOMAdapter.nodeTypes.ELEMENT_NODE, + { + path: currentPath, + namespace: ns, + prefix: prefix, + parent: parentContext + } + ); + if (ns && this.config.preserveNamespaces) { if (prefix) { // Create element with namespace and prefix @@ -128,7 +146,28 @@ export class JSONToXML { if (!attrName) return; const attrData = attrObj[attrName]; - const attrValue = attrData[valueKey] || ""; + + // Create attribute context + const attrContext = this.transformUtil.createContext( + 'json-to-xml', + nodeName, + DOMAdapter.nodeTypes.ELEMENT_NODE, + { + path: `${currentPath}.${attrName}`, + namespace: attrData[namespaceKey], + prefix: attrData[prefixKey], + isAttribute: true, + attributeName: attrName, + parent: context + } + ); + + // Apply transformations to attribute value + const transformedValue = this.transformUtil.applyTransforms( + attrData[valueKey] || "", + attrContext + ); + const attrNs = attrData[namespaceKey]; const attrPrefix = attrData[prefixKey]; @@ -142,7 +181,7 @@ export class JSONToXML { element, (attrNs && this.config.preserveNamespaces) ? attrNs : null, qualifiedName, - attrValue + transformedValue ); } ); @@ -150,7 +189,25 @@ export class JSONToXML { // Process simple text value if (nodeData[valueKey] !== undefined) { - element.textContent = nodeData[valueKey]; + // Apply transformations to text value + const textContext = this.transformUtil.createContext( + 'json-to-xml', + nodeName, + DOMAdapter.nodeTypes.TEXT_NODE, + { + path: `${currentPath}.#text`, + namespace: ns, + prefix: prefix, + parent: context + } + ); + + const transformedValue = this.transformUtil.applyTransforms( + nodeData[valueKey], + textContext + ); + + element.textContent = transformedValue; } // Process children @@ -171,8 +228,24 @@ export class JSONToXML { child[valueKey] !== undefined && this.config.preserveTextNodes ) { + // Apply transformations to text node + const textContext = this.transformUtil.createContext( + 'json-to-xml', + '#text', + DOMAdapter.nodeTypes.TEXT_NODE, + { + path: `${currentPath}.#text`, + parent: context + } + ); + + const transformedText = this.transformUtil.applyTransforms( + child[valueKey], + textContext + ); + element.appendChild( - DOMAdapter.createTextNode(this.xmlUtil.escapeXML(child[valueKey])) + DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText)) ); } // CDATA sections @@ -180,9 +253,25 @@ export class JSONToXML { child[cdataKey] !== undefined && this.config.preserveCDATA ) { + // Apply transformations to CDATA + const cdataContext = this.transformUtil.createContext( + 'json-to-xml', + '#cdata', + DOMAdapter.nodeTypes.CDATA_SECTION_NODE, + { + path: `${currentPath}.#cdata`, + parent: context + } + ); + + const transformedCData = this.transformUtil.applyTransforms( + child[cdataKey], + cdataContext + ); + element.appendChild( DOMAdapter.createCDATASection( - child[cdataKey] + transformedCData ) ); } @@ -214,7 +303,7 @@ export class JSONToXML { } // Element nodes (recursive) else { - const childElement = this.jsonToNode(child, doc); + const childElement = this.jsonToNode(child, doc, context, currentPath); if (childElement) { element.appendChild(childElement); } diff --git a/src/core/XMLToJSON.ts b/src/core/XmlToJsonConverter.ts similarity index 72% rename from src/core/XMLToJSON.ts rename to src/core/XmlToJsonConverter.ts index 9ce75c6..9254254 100644 --- a/src/core/XMLToJSON.ts +++ b/src/core/XmlToJsonConverter.ts @@ -2,9 +2,11 @@ * XMLToJSON class for converting XML to JSON with consistent namespace handling */ import { Configuration } from "./types/types"; -import { XMLToJSONError } from "./types/errors"; +import { XMLToJSONError } from "./types/Errors"; import { DOMAdapter } from "./DOMAdapter"; -import { JSONUtil } from "./utils/JSONUtil"; +import { JSONUtil } from "./utils/JsonUtils"; +import { TransformUtil } from "./transforms/TransformUtil"; +import { TransformContext } from "./transforms/ValueTransformer"; /** * XMLToJSON Parser for converting XML to JSON @@ -12,6 +14,7 @@ import { JSONUtil } from "./utils/JSONUtil"; export class XMLToJSON { private config: Configuration; private jsonUtil: JSONUtil; + private transformUtil: TransformUtil; /** * Constructor for XMLToJSON @@ -20,6 +23,7 @@ export class XMLToJSON { constructor(config: Configuration) { this.config = config; this.jsonUtil = new JSONUtil(this.config); + this.transformUtil = new TransformUtil(this.config); } /** @@ -50,9 +54,11 @@ export class XMLToJSON { /** * Convert a DOM node to JSON representation * @param node DOM node to convert + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the XML tree * @returns JSON representation of the node */ - private nodeToJson(node: Node): Record { + private nodeToJson(node: Node, parentContext?: TransformContext, path: string = ""): Record { const result: Record = {}; // Handle element nodes @@ -64,8 +70,24 @@ export class XMLToJSON { element.nodeName.split(":").pop() || element.nodeName; + // Update the current path + const currentPath = path ? `${path}.${nodeName}` : nodeName; + const nodeObj: Record = {}; + // Create context for this node + const context = this.transformUtil.createContext( + 'xml-to-json', + nodeName, + node.nodeType, + { + path: currentPath, + namespace: element.namespaceURI || undefined, + prefix: element.prefix || undefined, + parent: parentContext + } + ); + // Process namespaces if enabled if (this.config.preserveNamespaces) { const ns = element.namespaceURI; @@ -89,10 +111,31 @@ export class XMLToJSON { const attrLocalName = attr.localName || attr.name.split(":").pop() || attr.name; + // Create attribute context + const attrContext = this.transformUtil.createContext( + 'xml-to-json', + nodeName, + node.nodeType, + { + path: `${currentPath}.${attrLocalName}`, + namespace: attr.namespaceURI || undefined, + prefix: attr.prefix || undefined, + isAttribute: true, + attributeName: attrLocalName, + parent: context + } + ); + + // Apply transformations to attribute value + const transformedValue = this.transformUtil.applyTransforms( + attr.value, + attrContext + ); + // Create attribute object with consistent structure const attrObj: Record = { [attrLocalName]: { - [this.config.propNames.value]: attr.value, + [this.config.propNames.value]: transformedValue, }, }; @@ -146,7 +189,24 @@ export class XMLToJSON { text = text.trim(); } - children.push({ [valueKey]: text }); + // Create text node context + const textContext = this.transformUtil.createContext( + 'xml-to-json', + '#text', + child.nodeType, + { + path: `${currentPath}.#text`, + parent: context + } + ); + + // Apply transformations to text value + const transformedText = this.transformUtil.applyTransforms( + text, + textContext + ); + + children.push({ [valueKey]: transformedText }); } } // CDATA sections @@ -154,8 +214,25 @@ export class XMLToJSON { child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE && this.config.preserveCDATA ) { + // Create CDATA context + const cdataContext = this.transformUtil.createContext( + 'xml-to-json', + '#cdata', + child.nodeType, + { + path: `${currentPath}.#cdata`, + parent: context + } + ); + + // Apply transformations to CDATA value + const transformedCData = this.transformUtil.applyTransforms( + child.nodeValue || "", + cdataContext + ); + children.push({ - [cdataKey]: child.nodeValue || "", + [cdataKey]: transformedCData, }); } // Comments @@ -182,7 +259,7 @@ export class XMLToJSON { } // Element nodes (recursive) else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { - children.push(this.nodeToJson(child)); + children.push(this.nodeToJson(child, context, currentPath)); } } @@ -257,4 +334,4 @@ export class XMLToJSON { return node; } -} +} \ No newline at end of file diff --git a/src/core/transforms/BooleanTransformer.ts b/src/core/transforms/BooleanTransformer.ts new file mode 100644 index 0000000..b05c1aa --- /dev/null +++ b/src/core/transforms/BooleanTransformer.ts @@ -0,0 +1,101 @@ +/** + * Boolean value transformer for the XJX library + */ +import { ValueTransformer, TransformContext } from './ValueTransformer'; + +/** + * Interface for BooleanTransformer options + */ +export interface BooleanTransformerOptions { + /** + * Values to consider as true + */ + trueValues?: string[]; + + /** + * Values to consider as false + */ + falseValues?: string[]; +} + +/** + * Transforms string values to boolean types and vice versa + */ +export class BooleanTransformer extends ValueTransformer { + /** + * Values to consider as true + */ + private trueValues: string[]; + + /** + * Values to consider as false + */ + private falseValues: string[]; + + /** + * Lowercase versions of true values for case-insensitive comparison + */ + private trueValuesLower: string[]; + + /** + * Lowercase versions of false values for case-insensitive comparison + */ + private falseValuesLower: string[]; + + /** + * Creates a new BooleanTransformer + * @param options Transformer options + */ + constructor(options: BooleanTransformerOptions = {}) { + super(); + + // Set default values if not provided + this.trueValues = options.trueValues || ['true']; + this.falseValues = options.falseValues || ['false']; + + // Precompute lowercase versions for case-insensitive comparison + this.trueValuesLower = this.trueValues.map(v => String(v).toLowerCase()); + this.falseValuesLower = this.falseValues.map(v => String(v).toLowerCase()); + } + + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any { + // Only process strings in XML-to-JSON direction + if (typeof value !== 'string') return value; + + // Convert to lowercase for case-insensitive comparison + const valueLower = value.toLowerCase(); + + // Check against true values + if (this.trueValuesLower.includes(valueLower)) { + return true; + } + + // Check against false values + if (this.falseValuesLower.includes(valueLower)) { + return false; + } + + // If no transformation applies, return original value + return value; + } + + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any { + // Only process booleans in JSON-to-XML direction + if (typeof value !== 'boolean') return value; + + // Convert to string representation + return String(value); + } +} \ No newline at end of file diff --git a/src/core/transforms/NumberTransformer.ts b/src/core/transforms/NumberTransformer.ts new file mode 100644 index 0000000..cd4f811 --- /dev/null +++ b/src/core/transforms/NumberTransformer.ts @@ -0,0 +1,123 @@ +/** + * Number value transformer for the XJX library + */ +import { ValueTransformer, TransformContext } from './ValueTransformer'; + +/** + * Interface for NumberTransformer options + */ +export interface NumberTransformerOptions { + /** + * Whether to parse integers + */ + parseIntegers?: boolean; + + /** + * Whether to parse floating point numbers + */ + parseFloats?: boolean; + + /** + * Integer format in XML (if specified) + */ + integerFormat?: RegExp | string; + + /** + * Float format in XML (if specified) + */ + floatFormat?: RegExp | string; +} + +/** + * Transforms string values to number types and vice versa + */ +export class NumberTransformer extends ValueTransformer { + /** + * Whether to parse integers + */ + private parseIntegers: boolean; + + /** + * Whether to parse floating point numbers + */ + private parseFloats: boolean; + + /** + * Integer format in XML (if specified) + */ + private integerFormat?: RegExp; + + /** + * Float format in XML (if specified) + */ + private floatFormat?: RegExp; + + /** + * Creates a new NumberTransformer + * @param options Transformer options + */ + constructor(options: NumberTransformerOptions = {}) { + super(); + + // Set default values if not provided + this.parseIntegers = options.parseIntegers !== false; + this.parseFloats = options.parseFloats !== false; + + // Compile regex patterns if provided as strings + if (options.integerFormat) { + this.integerFormat = options.integerFormat instanceof RegExp + ? options.integerFormat + : new RegExp(options.integerFormat); + } else { + this.integerFormat = /^-?\d+$/; + } + + if (options.floatFormat) { + this.floatFormat = options.floatFormat instanceof RegExp + ? options.floatFormat + : new RegExp(options.floatFormat); + } else { + this.floatFormat = /^-?\d*\.\d+$/; + } + } + + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any { + // Only process strings in XML-to-JSON direction + if (typeof value !== 'string') return value; + + const trimmed = value.trim(); + + // Check for integers + if (this.parseIntegers && this.integerFormat!.test(trimmed)) { + return parseInt(trimmed, 10); + } + + // Check for floating point numbers + if (this.parseFloats && (this.floatFormat!.test(trimmed) || /^-?\d+\.\d+$/.test(trimmed))) { + return parseFloat(trimmed); + } + + // If no transformation applies, return original value + return value; + } + + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any { + // Only process numbers in JSON-to-XML direction + if (typeof value !== 'number') return value; + + // Convert to string representation + return String(value); + } +} \ No newline at end of file diff --git a/src/core/transforms/StringReplaceTransformer.ts b/src/core/transforms/StringReplaceTransformer.ts new file mode 100644 index 0000000..a2c68a8 --- /dev/null +++ b/src/core/transforms/StringReplaceTransformer.ts @@ -0,0 +1,101 @@ +/** + * String replacement transformer for the XJX library + */ +import { ValueTransformer, TransformContext } from './ValueTransformer'; + +/** + * Interface for StringReplaceTransformer options + */ +export interface StringReplaceTransformerOptions { + /** + * Regex pattern in string form "/pattern/flags" + */ + pattern?: string; + + /** + * Replacement string + */ + replacement?: string; +} + +/** + * Transforms string values by applying regex replacements + */ +export class StringReplaceTransformer extends ValueTransformer { + /** + * Regex pattern to match + */ + private regex: RegExp; + + /** + * Replacement string + */ + private replacement: string; + + /** + * Creates a StringReplaceTransformer + * @param options Configuration options + */ + constructor(options: StringReplaceTransformerOptions = {}) { + super(); + + this.replacement = options.replacement || ''; + + // Parse and compile the regex from string representation + try { + // Extract pattern and flags from the string format "/pattern/flags" + const patternStr = options.pattern || ''; + const matches = patternStr.match(/^\/(.*?)\/([gimyus]*)$/); + + if (matches) { + const [, pattern, flags] = matches; + this.regex = new RegExp(pattern, flags); + } else { + // If not in /pattern/flags format, treat the whole string as a literal pattern + this.regex = new RegExp(patternStr); + } + } catch (error) { + console.error(`Invalid regex pattern: ${error instanceof Error ? error.message : String(error)}`); + // Create a safe fallback regex that won't match anything + this.regex = new RegExp('(?!)'); + } + } + + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any { + // Only process string values + if (typeof value !== 'string') return value; + + try { + // Apply the regex replacement + return value.replace(this.regex, this.replacement); + } catch (error) { + console.error(`Error applying string replacement: ${error instanceof Error ? error.message : String(error)}`); + return value; + } + } + + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any { + // Only process string values + if (typeof value !== 'string') return value; + + try { + // Apply the regex replacement + return value.replace(this.regex, this.replacement); + } catch (error) { + console.error(`Error applying string replacement: ${error instanceof Error ? error.message : String(error)}`); + return value; + } + } +} \ No newline at end of file diff --git a/src/core/transforms/TransformUtil.ts b/src/core/transforms/TransformUtil.ts new file mode 100644 index 0000000..428145e --- /dev/null +++ b/src/core/transforms/TransformUtil.ts @@ -0,0 +1,86 @@ +/** + * Utilities for applying value transformations + */ +import { Configuration } from '../types/types'; +import { TransformContext, TransformDirection } from './ValueTransformer'; +import { DOMAdapter } from '../DOMAdapter'; + +/** + * Utility for applying value transformations + */ +export class TransformUtil { + private config: Configuration; + + /** + * Create a new TransformUtil + * @param config Configuration + */ + constructor(config: Configuration) { + this.config = config; + } + + /** + * Apply transforms to a value + * @param value Value to transform + * @param context Transformation context + * @returns Transformed value + */ + applyTransforms(value: any, context: TransformContext): any { + // Skip transformation if no transformers are configured + if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) { + return value; + } + + // Apply each transformer in sequence + let transformedValue = value; + for (const transformer of this.config.valueTransforms) { + transformedValue = transformer.process(transformedValue, context); + } + + return transformedValue; + } + + /** + * Create a transform context + * @param direction Direction of transformation + * @param nodeName Name of the current node + * @param nodeType DOM node type + * @param options Additional context options + * @returns Transform context + */ + createContext( + direction: TransformDirection, + nodeName: string, + nodeType: number, + options: { + path?: string; + namespace?: string; + prefix?: string; + isAttribute?: boolean; + attributeName?: string; + parent?: TransformContext; + } = {} + ): TransformContext { + return { + direction, + nodeName, + nodeType, + path: options.path || nodeName, + namespace: options.namespace, + prefix: options.prefix, + isAttribute: options.isAttribute || false, + attributeName: options.attributeName, + parent: options.parent, + config: this.config, + }; + } + + /** + * Get a user-friendly node type name for debugging + * @param nodeType DOM node type + * @returns String representation of node type + */ + getNodeTypeName(nodeType: number): string { + return DOMAdapter.getNodeTypeName(nodeType); + } +} \ No newline at end of file diff --git a/src/core/transforms/ValueTransformer.ts b/src/core/transforms/ValueTransformer.ts new file mode 100644 index 0000000..598e52f --- /dev/null +++ b/src/core/transforms/ValueTransformer.ts @@ -0,0 +1,75 @@ +/** + * Value transformation types and base class for the XJX library + */ +import { Configuration } from '../types/types'; + +/** + * Direction of the transformation + */ +export type TransformDirection = 'xml-to-json' | 'json-to-xml'; + +/** + * Context provided to value transformers + */ +export interface TransformContext { + // Core transformation info + direction: TransformDirection; // Direction of the current transformation + + // Node information + nodeName: string; // Name of the current node + nodeType: number; // DOM node type (element, text, etc.) + namespace?: string; // Namespace URI if available + prefix?: string; // Namespace prefix if available + + // Structure information + path: string; // Dot-notation path to current node + isAttribute: boolean; // Whether the current value is from an attribute + attributeName?: string; // Name of attribute if isAttribute is true + + // Parent context (creates a chain) + parent?: TransformContext; // Reference to parent context for traversal + + // Configuration reference + config: Configuration; // Reference to the current configuration +} + +/** + * Abstract base class for value transformers + */ +export abstract class ValueTransformer { + /** + * Process a value, transforming it if applicable + * @param value Value to potentially transform + * @param context Context including direction and other information + * @returns Transformed value or original if not applicable + */ + process(value: any, context: TransformContext): any { + if (context.direction === 'xml-to-json') { + return this.xmlToJson(value, context); + } else { + return this.jsonToXml(value, context); + } + } + + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any { + // Default implementation returns original value + return value; + } + + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any { + // Default implementation returns original value + return value; + } +} \ No newline at end of file diff --git a/src/core/transforms/index.ts b/src/core/transforms/index.ts new file mode 100644 index 0000000..56aaf34 --- /dev/null +++ b/src/core/transforms/index.ts @@ -0,0 +1,16 @@ +/** + * Value transformers for the XJX library + */ + +// Export base transformer +export { ValueTransformer, TransformContext, TransformDirection } from './ValueTransformer'; + +// Export concrete transformers +export { BooleanTransformer, BooleanTransformerOptions } from './BooleanTransformer'; +export { NumberTransformer, NumberTransformerOptions } from './NumberTransformer'; +export { StringReplaceTransformer, StringReplaceTransformerOptions } from './StringReplaceTransformer'; + +// Export utility class +export { TransformUtil } from './TransformUtil'; + +// Add more transformers here in the future \ No newline at end of file diff --git a/src/core/types/types.ts b/src/core/types/types.ts index 4caed20..dd93687 100644 --- a/src/core/types/types.ts +++ b/src/core/types/types.ts @@ -1,6 +1,7 @@ /** * Type definitions for the XJX library */ +import { ValueTransformer } from '../transforms/ValueTransformer'; /** * Configuration interface for the library @@ -38,6 +39,9 @@ export interface Configuration { target: string; children: string; }; + + // Value transformers + valueTransforms?: ValueTransformer[]; } export default Configuration; \ No newline at end of file diff --git a/src/core/utils/JSONUtil.ts b/src/core/utils/JsonUtils.ts similarity index 100% rename from src/core/utils/JSONUtil.ts rename to src/core/utils/JsonUtils.ts diff --git a/src/core/utils/XMLUtil.ts b/src/core/utils/XmlUtils.ts similarity index 99% rename from src/core/utils/XMLUtil.ts rename to src/core/utils/XmlUtils.ts index b6b57d7..0a77985 100644 --- a/src/core/utils/XMLUtil.ts +++ b/src/core/utils/XmlUtils.ts @@ -1,7 +1,7 @@ /** * XMLUtil - Utility functions for XML processing */ -import { XMLToJSONError } from "../types/errors"; +import { XMLToJSONError } from "../types/Errors"; import { DOMAdapter } from "../DOMAdapter"; import { Configuration } from "../types/types"; diff --git a/src/index.ts b/src/index.ts index f038c2f..bd6ddd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,27 +2,38 @@ * XJX Library - Main entry point */ import { XJX } from "./XJX"; -import { XMLToJSON } from "./core/XMLToJSON"; -import { JSONToXML } from "./core/JSONToXML"; +import { XMLToJSON } from "./core/XmlToJsonConverter"; +import { JSONToXML } from "./core/JsonToXmlConverter"; import { DOMAdapter } from "./core/DOMAdapter"; import { Configuration } from "./core/types/types"; import { DEFAULT_CONFIG } from "./core/config/config"; -import { JSONUtil } from "./core/utils/JSONUtil"; -import { XMLUtil } from "./core/utils/XMLUtil"; +import { JSONUtil } from "./core/utils/JsonUtils"; +import { XMLUtil } from "./core/utils/XmlUtils"; -import * as errors from "./core/types/errors"; +// Import transformers +import { ValueTransformer } from "./core/transforms/ValueTransformer"; +import { BooleanTransformer } from "./core/transforms/BooleanTransformer"; +import { NumberTransformer } from "./core/transforms/NumberTransformer"; +import { StringReplaceTransformer } from "./core/transforms/StringReplaceTransformer"; -// Re-export all classes and types +import * as errors from "./core/types/Errors"; + +// Re-export all classes and types (minimal approach) export { XJX, XMLToJSON, JSONToXML, DOMAdapter, - Configuration as XMLToJSONConfig, + Configuration, DEFAULT_CONFIG, JSONUtil, XMLUtil, errors, + // Export only ValueTransformer and concrete transformers + ValueTransformer, + BooleanTransformer, + NumberTransformer, + StringReplaceTransformer }; // Default export for easier importing From 85c1956b8981eb7936e3e2ea5ff2807db1445854 Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 10:51:03 -0500 Subject: [PATCH 28/38] build updates --- .gitignore | 3 +- dist/dts/XJX.d.ts | 64 + dist/dts/core/DOMAdapter.d.ts | 40 + dist/dts/core/JsonToXmlConverter.d.ts | 32 + dist/dts/core/XmlToJsonConverter.d.ts | 32 + dist/dts/core/config/config.d.ts | 8 + .../core/transforms/BooleanTransformer.d.ts | 57 + .../core/transforms/NumberTransformer.d.ts | 65 + .../transforms/StringReplaceTransformer.d.ts | 49 + dist/dts/core/transforms/TransformUtil.d.ts | 45 + .../dts/core/transforms/ValueTransformer.d.ts | 49 + dist/dts/core/transforms/index.d.ts | 8 + dist/dts/core/types/errors.d.ts | 33 + dist/dts/core/types/types.d.ts | 38 + dist/dts/core/utils/JsonUtils.d.ts | 72 + dist/dts/core/utils/XmlUtils.d.ts | 61 + dist/dts/index.d.ts | 7 + dist/index.d.ts | 171 + dist/index.js | 1389 +++++ dist/index.js.map | 1 + dist/stats.html | 4949 +++++++++++++++++ dist/xjx.min.js | 2 + dist/xjx.min.js.map | 1 + dist/xjx.umd.js | 1403 +++++ dist/xjx.umd.js.map | 1 + package-lock.json | 14 + package.json | 4 +- src/XJX.ts | 38 +- src/core/DOMAdapter.ts | 34 +- src/core/JsonToXmlConverter.ts | 4 +- src/core/XmlToJsonConverter.ts | 6 +- src/core/types/errors.ts | 10 +- src/core/utils/XmlUtils.ts | 4 +- src/index.ts | 46 +- 34 files changed, 8637 insertions(+), 103 deletions(-) create mode 100644 dist/dts/XJX.d.ts create mode 100644 dist/dts/core/DOMAdapter.d.ts create mode 100644 dist/dts/core/JsonToXmlConverter.d.ts create mode 100644 dist/dts/core/XmlToJsonConverter.d.ts create mode 100644 dist/dts/core/config/config.d.ts create mode 100644 dist/dts/core/transforms/BooleanTransformer.d.ts create mode 100644 dist/dts/core/transforms/NumberTransformer.d.ts create mode 100644 dist/dts/core/transforms/StringReplaceTransformer.d.ts create mode 100644 dist/dts/core/transforms/TransformUtil.d.ts create mode 100644 dist/dts/core/transforms/ValueTransformer.d.ts create mode 100644 dist/dts/core/transforms/index.d.ts create mode 100644 dist/dts/core/types/errors.d.ts create mode 100644 dist/dts/core/types/types.d.ts create mode 100644 dist/dts/core/utils/JsonUtils.d.ts create mode 100644 dist/dts/core/utils/XmlUtils.d.ts create mode 100644 dist/dts/index.d.ts create mode 100644 dist/index.d.ts create mode 100644 dist/index.js create mode 100644 dist/index.js.map create mode 100644 dist/stats.html create mode 100644 dist/xjx.min.js create mode 100644 dist/xjx.min.js.map create mode 100644 dist/xjx.umd.js create mode 100644 dist/xjx.umd.js.map diff --git a/.gitignore b/.gitignore index 35dd455..a8d3138 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,11 @@ node_modules/ # Build output -dist/ +# dist/ build/ lib/ out/ +reports/ # TypeScript cache *.tsbuildinfo diff --git a/dist/dts/XJX.d.ts b/dist/dts/XJX.d.ts new file mode 100644 index 0000000..3d59135 --- /dev/null +++ b/dist/dts/XJX.d.ts @@ -0,0 +1,64 @@ +import { Configuration } from "./core/types/types"; +import { ValueTransformer } from "./core/transforms"; +export declare class XJX { + private config; + private xmltojson; + private jsontoxml; + private jsonUtil; + private xmlUtil; + /** + * Constructor for XJX utility + * @param config Configuration options + */ + constructor(config?: Partial); + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + xmlToJson(xmlString: string): Record; + /** + * Convert JSON object back to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + jsonToXml(jsonObj: Record): string; + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + prettyPrintXml(xmlString: string): string; + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns The value at the specified path or the fallback value + */ + getPath(obj: Record, path: string, fallback?: any): any; + /** + * Validate XML string + * @param xmlString XML string to validate + * @returns Validation result + */ + validateXML(xmlString: string): { + isValid: boolean; + message?: string; + }; + /** + * Add a value transformer to the configuration + * @param transformer Value transformer to add + * @returns This XJX instance for chaining + */ + addTransformer(transformer: ValueTransformer): XJX; + /** + * Removes all value transformers from the configuration + * @returns This XJX instance for chaining + */ + clearTransformers(): XJX; + /** + * Clean up any resources + */ + cleanup(): void; +} diff --git a/dist/dts/core/DOMAdapter.d.ts b/dist/dts/core/DOMAdapter.d.ts new file mode 100644 index 0000000..acb3b33 --- /dev/null +++ b/dist/dts/core/DOMAdapter.d.ts @@ -0,0 +1,40 @@ +interface NodeTypes { + ELEMENT_NODE: number; + TEXT_NODE: number; + CDATA_SECTION_NODE: number; + COMMENT_NODE: number; + PROCESSING_INSTRUCTION_NODE: number; + DOCUMENT_NODE: number; +} +export declare const DOMAdapter: { + createParser: () => any; + createSerializer: () => any; + nodeTypes: NodeTypes; + parseFromString: (xmlString: string, contentType?: string) => any; + serializeToString: (node: Node) => any; + createDocument: () => any; + createElement: (tagName: string) => any; + createElementNS: (namespaceURI: string, qualifiedName: string) => any; + createTextNode: (data: string) => any; + createCDATASection: (data: string) => any; + createComment: (data: string) => any; + createProcessingInstruction: (target: string, data: string) => any; + /** + * Creates a proper namespace qualified attribute + */ + setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string) => void; + /** + * Check if an object is a DOM node + */ + isNode: (obj: any) => boolean; + /** + * Get DOM node type as string for debugging + */ + getNodeTypeName: (nodeType: number) => string; + /** + * Get all node attributes as an object + */ + getNodeAttributes: (node: Element) => Record; + cleanup: () => void; +}; +export {}; diff --git a/dist/dts/core/JsonToXmlConverter.d.ts b/dist/dts/core/JsonToXmlConverter.d.ts new file mode 100644 index 0000000..2c2c4f9 --- /dev/null +++ b/dist/dts/core/JsonToXmlConverter.d.ts @@ -0,0 +1,32 @@ +/** + * JSONToXML class for converting JSON to XML with consistent namespace handling + */ +import { Configuration } from "./types/types"; +/** + * JSONToXML for converting JSON to XML + */ +export declare class JSONToXML { + private config; + private xmlUtil; + private transformUtil; + /** + * Constructor for JSONToXML + * @param config Configuration options + */ + constructor(config: Configuration); + /** + * Convert JSON object to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + serialize(jsonObj: Record): string; + /** + * Convert JSON object to DOM node + * @param jsonObj JSON object to convert + * @param doc Document for creating elements + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the JSON object + * @returns DOM Element + */ + private jsonToNode; +} diff --git a/dist/dts/core/XmlToJsonConverter.d.ts b/dist/dts/core/XmlToJsonConverter.d.ts new file mode 100644 index 0000000..54e7ac9 --- /dev/null +++ b/dist/dts/core/XmlToJsonConverter.d.ts @@ -0,0 +1,32 @@ +/** + * XMLToJSON class for converting XML to JSON with consistent namespace handling + */ +import { Configuration } from "./types/types"; +/** + * XMLToJSON Parser for converting XML to JSON + */ +export declare class XMLToJSON { + private config; + private jsonUtil; + private transformUtil; + /** + * Constructor for XMLToJSON + * @param config Configuration options + */ + constructor(config: Configuration); + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + parse(xmlString: string): Record; + /** + * Convert a DOM node to JSON representation + * @param node DOM node to convert + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the XML tree + * @returns JSON representation of the node + */ + private nodeToJson; + private cleanNode; +} diff --git a/dist/dts/core/config/config.d.ts b/dist/dts/core/config/config.d.ts new file mode 100644 index 0000000..c4943ea --- /dev/null +++ b/dist/dts/core/config/config.d.ts @@ -0,0 +1,8 @@ +/** + * Default configuration for the XJX library + */ +import { Configuration } from '../types/types'; +/** + * Default configuration + */ +export declare const DEFAULT_CONFIG: Configuration; diff --git a/dist/dts/core/transforms/BooleanTransformer.d.ts b/dist/dts/core/transforms/BooleanTransformer.d.ts new file mode 100644 index 0000000..c60a5ee --- /dev/null +++ b/dist/dts/core/transforms/BooleanTransformer.d.ts @@ -0,0 +1,57 @@ +/** + * Boolean value transformer for the XJX library + */ +import { ValueTransformer, TransformContext } from './ValueTransformer'; +/** + * Interface for BooleanTransformer options + */ +export interface BooleanTransformerOptions { + /** + * Values to consider as true + */ + trueValues?: string[]; + /** + * Values to consider as false + */ + falseValues?: string[]; +} +/** + * Transforms string values to boolean types and vice versa + */ +export declare class BooleanTransformer extends ValueTransformer { + /** + * Values to consider as true + */ + private trueValues; + /** + * Values to consider as false + */ + private falseValues; + /** + * Lowercase versions of true values for case-insensitive comparison + */ + private trueValuesLower; + /** + * Lowercase versions of false values for case-insensitive comparison + */ + private falseValuesLower; + /** + * Creates a new BooleanTransformer + * @param options Transformer options + */ + constructor(options?: BooleanTransformerOptions); + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any; + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any; +} diff --git a/dist/dts/core/transforms/NumberTransformer.d.ts b/dist/dts/core/transforms/NumberTransformer.d.ts new file mode 100644 index 0000000..af0cc83 --- /dev/null +++ b/dist/dts/core/transforms/NumberTransformer.d.ts @@ -0,0 +1,65 @@ +/** + * Number value transformer for the XJX library + */ +import { ValueTransformer, TransformContext } from './ValueTransformer'; +/** + * Interface for NumberTransformer options + */ +export interface NumberTransformerOptions { + /** + * Whether to parse integers + */ + parseIntegers?: boolean; + /** + * Whether to parse floating point numbers + */ + parseFloats?: boolean; + /** + * Integer format in XML (if specified) + */ + integerFormat?: RegExp | string; + /** + * Float format in XML (if specified) + */ + floatFormat?: RegExp | string; +} +/** + * Transforms string values to number types and vice versa + */ +export declare class NumberTransformer extends ValueTransformer { + /** + * Whether to parse integers + */ + private parseIntegers; + /** + * Whether to parse floating point numbers + */ + private parseFloats; + /** + * Integer format in XML (if specified) + */ + private integerFormat?; + /** + * Float format in XML (if specified) + */ + private floatFormat?; + /** + * Creates a new NumberTransformer + * @param options Transformer options + */ + constructor(options?: NumberTransformerOptions); + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any; + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any; +} diff --git a/dist/dts/core/transforms/StringReplaceTransformer.d.ts b/dist/dts/core/transforms/StringReplaceTransformer.d.ts new file mode 100644 index 0000000..1f27bbf --- /dev/null +++ b/dist/dts/core/transforms/StringReplaceTransformer.d.ts @@ -0,0 +1,49 @@ +/** + * String replacement transformer for the XJX library + */ +import { ValueTransformer, TransformContext } from './ValueTransformer'; +/** + * Interface for StringReplaceTransformer options + */ +export interface StringReplaceTransformerOptions { + /** + * Regex pattern in string form "/pattern/flags" + */ + pattern?: string; + /** + * Replacement string + */ + replacement?: string; +} +/** + * Transforms string values by applying regex replacements + */ +export declare class StringReplaceTransformer extends ValueTransformer { + /** + * Regex pattern to match + */ + private regex; + /** + * Replacement string + */ + private replacement; + /** + * Creates a StringReplaceTransformer + * @param options Configuration options + */ + constructor(options?: StringReplaceTransformerOptions); + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any; + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any; +} diff --git a/dist/dts/core/transforms/TransformUtil.d.ts b/dist/dts/core/transforms/TransformUtil.d.ts new file mode 100644 index 0000000..0045073 --- /dev/null +++ b/dist/dts/core/transforms/TransformUtil.d.ts @@ -0,0 +1,45 @@ +/** + * Utilities for applying value transformations + */ +import { Configuration } from '../types/types'; +import { TransformContext, TransformDirection } from './ValueTransformer'; +/** + * Utility for applying value transformations + */ +export declare class TransformUtil { + private config; + /** + * Create a new TransformUtil + * @param config Configuration + */ + constructor(config: Configuration); + /** + * Apply transforms to a value + * @param value Value to transform + * @param context Transformation context + * @returns Transformed value + */ + applyTransforms(value: any, context: TransformContext): any; + /** + * Create a transform context + * @param direction Direction of transformation + * @param nodeName Name of the current node + * @param nodeType DOM node type + * @param options Additional context options + * @returns Transform context + */ + createContext(direction: TransformDirection, nodeName: string, nodeType: number, options?: { + path?: string; + namespace?: string; + prefix?: string; + isAttribute?: boolean; + attributeName?: string; + parent?: TransformContext; + }): TransformContext; + /** + * Get a user-friendly node type name for debugging + * @param nodeType DOM node type + * @returns String representation of node type + */ + getNodeTypeName(nodeType: number): string; +} diff --git a/dist/dts/core/transforms/ValueTransformer.d.ts b/dist/dts/core/transforms/ValueTransformer.d.ts new file mode 100644 index 0000000..40e32e2 --- /dev/null +++ b/dist/dts/core/transforms/ValueTransformer.d.ts @@ -0,0 +1,49 @@ +/** + * Value transformation types and base class for the XJX library + */ +import { Configuration } from '../types/types'; +/** + * Direction of the transformation + */ +export type TransformDirection = 'xml-to-json' | 'json-to-xml'; +/** + * Context provided to value transformers + */ +export interface TransformContext { + direction: TransformDirection; + nodeName: string; + nodeType: number; + namespace?: string; + prefix?: string; + path: string; + isAttribute: boolean; + attributeName?: string; + parent?: TransformContext; + config: Configuration; +} +/** + * Abstract base class for value transformers + */ +export declare abstract class ValueTransformer { + /** + * Process a value, transforming it if applicable + * @param value Value to potentially transform + * @param context Context including direction and other information + * @returns Transformed value or original if not applicable + */ + process(value: any, context: TransformContext): any; + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any; + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any; +} diff --git a/dist/dts/core/transforms/index.d.ts b/dist/dts/core/transforms/index.d.ts new file mode 100644 index 0000000..579d931 --- /dev/null +++ b/dist/dts/core/transforms/index.d.ts @@ -0,0 +1,8 @@ +/** + * Value transformers for the XJX library + */ +export { ValueTransformer, TransformContext, TransformDirection } from './ValueTransformer'; +export { BooleanTransformer, BooleanTransformerOptions } from './BooleanTransformer'; +export { NumberTransformer, NumberTransformerOptions } from './NumberTransformer'; +export { StringReplaceTransformer, StringReplaceTransformerOptions } from './StringReplaceTransformer'; +export { TransformUtil } from './TransformUtil'; diff --git a/dist/dts/core/types/errors.d.ts b/dist/dts/core/types/errors.d.ts new file mode 100644 index 0000000..14ee611 --- /dev/null +++ b/dist/dts/core/types/errors.d.ts @@ -0,0 +1,33 @@ +/** + * Error classes for the XJX library + */ +/** + * Base error class + */ +export declare class XJXError extends Error { + constructor(message: string); +} +/** + * Error for XML parsing issues + */ +export declare class XMLParseError extends XJXError { + constructor(message: string); +} +/** + * Error for XML serialization issues + */ +export declare class XMLSerializeError extends XJXError { + constructor(message: string); +} +/** + * Error for environment incompatibility + */ +export declare class EnvironmentError extends XJXError { + constructor(message: string); +} +/** + * Error for invalid configuration + */ +export declare class ConfigurationError extends XJXError { + constructor(message: string); +} diff --git a/dist/dts/core/types/types.d.ts b/dist/dts/core/types/types.d.ts new file mode 100644 index 0000000..9eb379b --- /dev/null +++ b/dist/dts/core/types/types.d.ts @@ -0,0 +1,38 @@ +/** + * Type definitions for the XJX library + */ +import { ValueTransformer } from '../transforms/ValueTransformer'; +/** + * Configuration interface for the library + */ +export interface Configuration { + preserveNamespaces: boolean; + preserveComments: boolean; + preserveProcessingInstr: boolean; + preserveCDATA: boolean; + preserveTextNodes: boolean; + preserveWhitespace: boolean; + preserveAttributes: boolean; + outputOptions: { + prettyPrint: boolean; + indent: number; + compact: boolean; + json: Record; + xml: { + declaration: boolean; + }; + }; + propNames: { + namespace: string; + prefix: string; + attributes: string; + value: string; + cdata: string; + comments: string; + instruction: string; + target: string; + children: string; + }; + valueTransforms?: ValueTransformer[]; +} +export default Configuration; diff --git a/dist/dts/core/utils/JsonUtils.d.ts b/dist/dts/core/utils/JsonUtils.d.ts new file mode 100644 index 0000000..e7dfb63 --- /dev/null +++ b/dist/dts/core/utils/JsonUtils.d.ts @@ -0,0 +1,72 @@ +/** + * JSONUtil - Utility functions for JSON processing + */ +import { Configuration } from "../types/types"; +export declare class JSONUtil { + private config; + /** + * Constructor for JSONUtil + * @param config Configuration options + */ + constructor(config: Configuration); + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * Automatically traverses into children arrays and flattens results. + * + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns Retrieved value or fallback + */ + getPath(obj: Record, path: string, fallback?: any): any; + /** + * Resolves a single path segment in the context of a JSON object. + * Falls back to searching children for matching keys. + * + * @param obj The current object + * @param segment The path segment to resolve + * @returns Resolved value or undefined + */ + private resolveSegment; + /** + * Converts a plain JSON object to the XML-like JSON structure. + * Optionally wraps the result in a root element with attributes and namespaces. + * + * @param obj Standard JSON object + * @param root Optional root element configuration (either a string or object with $ keys) + * @returns XML-like JSON object + */ + fromJSONObject(obj: any, root?: any): any; + /** + * Wraps a standard JSON value in the XML-like JSON structure + * @param value Value to wrap + * @returns Wrapped value + */ + private wrapObject; + /** + * Check if an object is empty + * @param value Value to check + * @returns true if empty + */ + isEmpty(value: any): boolean; + /** + * Safely stringify JSON for debugging + * @param obj Object to stringify + * @param indent Optional indentation level + * @returns JSON string representation + */ + safeStringify(obj: any, indent?: number): string; + /** + * Deep clone an object + * @param obj Object to clone + * @returns Cloned object + */ + deepClone(obj: any): any; + /** + * Deep merge two objects with proper type handling + * @param target Target object + * @param source Source object + * @returns Merged object (target is modified) + */ + deepMerge(target: T, source: Partial): T; +} diff --git a/dist/dts/core/utils/XmlUtils.d.ts b/dist/dts/core/utils/XmlUtils.d.ts new file mode 100644 index 0000000..5ca0a0d --- /dev/null +++ b/dist/dts/core/utils/XmlUtils.d.ts @@ -0,0 +1,61 @@ +import { Configuration } from "../types/types"; +export declare class XMLUtil { + private config; + /** + * Constructor for XMLUtil + * @param config Configuration options + */ + constructor(config: Configuration); + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + prettyPrintXml(xmlString: string): string; + /** + * Check if XML string is well-formed + * @param xmlString XML string to validate + * @returns Object with validation result and any error messages + */ + validateXML(xmlString: string): { + isValid: boolean; + message?: string; + }; + /** + * Add XML declaration to a string if missing + * @param xmlString XML string + * @returns XML string with declaration + */ + ensureXMLDeclaration(xmlString: string): string; + /** + * Escapes special characters in text for safe XML usage. + * @param text Text to escape. + * @returns Escaped XML string. + */ + escapeXML(text: string): string; + /** + * Unescapes XML entities back to their character equivalents. + * @param text Text with XML entities. + * @returns Unescaped text. + */ + unescapeXML(text: string): string; + /** + * Extract the namespace prefix from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Prefix or null if no prefix + */ + extractPrefix(qualifiedName: string): string | null; + /** + * Extract the local name from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Local name + */ + extractLocalName(qualifiedName: string): string; + /** + * Create a qualified name from prefix and local name + * @param prefix Namespace prefix (can be null) + * @param localName Local name + * @returns Qualified name + */ + createQualifiedName(prefix: string | null, localName: string): string; +} diff --git a/dist/dts/index.d.ts b/dist/dts/index.d.ts new file mode 100644 index 0000000..2aa2f9d --- /dev/null +++ b/dist/dts/index.d.ts @@ -0,0 +1,7 @@ +import { XJX } from './XJX'; +export { XJX }; +export { Configuration } from './core/types/types'; +export { DEFAULT_CONFIG } from './core/config/config'; +export { XJXError } from './core/types/errors'; +export { ValueTransformer } from './core/transforms/ValueTransformer'; +export default XJX; diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..e6f73e0 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,171 @@ +/** + * Value transformation types and base class for the XJX library + */ + +/** + * Direction of the transformation + */ +type TransformDirection = 'xml-to-json' | 'json-to-xml'; +/** + * Context provided to value transformers + */ +interface TransformContext { + direction: TransformDirection; + nodeName: string; + nodeType: number; + namespace?: string; + prefix?: string; + path: string; + isAttribute: boolean; + attributeName?: string; + parent?: TransformContext; + config: Configuration; +} +/** + * Abstract base class for value transformers + */ +declare abstract class ValueTransformer { + /** + * Process a value, transforming it if applicable + * @param value Value to potentially transform + * @param context Context including direction and other information + * @returns Transformed value or original if not applicable + */ + process(value: any, context: TransformContext): any; + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + protected xmlToJson(value: any, context: TransformContext): any; + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + protected jsonToXml(value: any, context: TransformContext): any; +} + +/** + * Type definitions for the XJX library + */ + +/** + * Configuration interface for the library + */ +interface Configuration { + preserveNamespaces: boolean; + preserveComments: boolean; + preserveProcessingInstr: boolean; + preserveCDATA: boolean; + preserveTextNodes: boolean; + preserveWhitespace: boolean; + preserveAttributes: boolean; + outputOptions: { + prettyPrint: boolean; + indent: number; + compact: boolean; + json: Record; + xml: { + declaration: boolean; + }; + }; + propNames: { + namespace: string; + prefix: string; + attributes: string; + value: string; + cdata: string; + comments: string; + instruction: string; + target: string; + children: string; + }; + valueTransforms?: ValueTransformer[]; +} + +declare class XJX { + private config; + private xmltojson; + private jsontoxml; + private jsonUtil; + private xmlUtil; + /** + * Constructor for XJX utility + * @param config Configuration options + */ + constructor(config?: Partial); + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + xmlToJson(xmlString: string): Record; + /** + * Convert JSON object back to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + jsonToXml(jsonObj: Record): string; + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + prettyPrintXml(xmlString: string): string; + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns The value at the specified path or the fallback value + */ + getPath(obj: Record, path: string, fallback?: any): any; + /** + * Validate XML string + * @param xmlString XML string to validate + * @returns Validation result + */ + validateXML(xmlString: string): { + isValid: boolean; + message?: string; + }; + /** + * Add a value transformer to the configuration + * @param transformer Value transformer to add + * @returns This XJX instance for chaining + */ + addTransformer(transformer: ValueTransformer): XJX; + /** + * Removes all value transformers from the configuration + * @returns This XJX instance for chaining + */ + clearTransformers(): XJX; + /** + * Clean up any resources + */ + cleanup(): void; +} + +/** + * Default configuration for the XJX library + */ + +/** + * Default configuration + */ +declare const DEFAULT_CONFIG: Configuration; + +/** + * Error classes for the XJX library + */ +/** + * Base error class + */ +declare class XJXError extends Error { + constructor(message: string); +} + +export { Configuration, DEFAULT_CONFIG, ValueTransformer, XJX, XJXError, XJX as default }; diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..121cb42 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,1389 @@ +/** + * Error classes for the XJX library + */ +/** + * Base error class + */ +class XJXError extends Error { + constructor(message) { + super(message); + this.name = 'XMLToJSONError'; + } +} + +/** + * DOM Environment provider with unified interface for browser and Node.js + */ +const DOMAdapter = (() => { + // Environment-specific DOM implementation + let domParser; + let xmlSerializer; + let nodeTypes; + let docImplementation; + let jsdomInstance = null; + try { + if (typeof window === "undefined") { + // Node.js environment - try JSDOM first + try { + const { JSDOM } = require("jsdom"); + jsdomInstance = new JSDOM("", { + contentType: "text/xml", + }); + domParser = jsdomInstance.window.DOMParser; + xmlSerializer = jsdomInstance.window.XMLSerializer; + nodeTypes = { + ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE, + TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE, + CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE, + COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE, + PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE, + DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line + }; + docImplementation = jsdomInstance.window.document.implementation; + } + catch (jsdomError) { + // Fall back to xmldom if JSDOM isn't available + try { + const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom'); + domParser = DOMParser; + xmlSerializer = XMLSerializer; + // Standard DOM node types + nodeTypes = { + ELEMENT_NODE: 1, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + COMMENT_NODE: 8, + PROCESSING_INSTRUCTION_NODE: 7, + DOCUMENT_NODE: 9, + }; + const implementation = new DOMImplementation(); + docImplementation = implementation; + } + catch (xmldomError) { + throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`); + } + } + } + else { + // Browser environment + if (!window.DOMParser) { + throw new XJXError("DOMParser is not available in this environment"); + } + if (!window.XMLSerializer) { + throw new XJXError("XMLSerializer is not available in this environment"); + } + domParser = window.DOMParser; + xmlSerializer = window.XMLSerializer; + nodeTypes = { + ELEMENT_NODE: Node.ELEMENT_NODE, + TEXT_NODE: Node.TEXT_NODE, + CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE, + COMMENT_NODE: Node.COMMENT_NODE, + PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE, + DOCUMENT_NODE: Node.DOCUMENT_NODE, + }; + docImplementation = document.implementation; + } + } + catch (error) { + throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`); + } + return { + createParser: () => { + try { + return new domParser(); + } + catch (error) { + throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createSerializer: () => { + try { + return new xmlSerializer(); + } + catch (error) { + throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`); + } + }, + nodeTypes, + parseFromString: (xmlString, contentType = 'text/xml') => { + try { + const parser = new domParser(); + return parser.parseFromString(xmlString, contentType); + } + catch (error) { + throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`); + } + }, + serializeToString: (node) => { + try { + const serializer = new xmlSerializer(); + return serializer.serializeToString(node); + } + catch (error) { + throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createDocument: () => { + try { + // For browsers, create a document with a root element to avoid issues + if (typeof window !== "undefined") { + const parser = new domParser(); + return parser.parseFromString('', 'text/xml'); + } + else { + return docImplementation.createDocument(null, null, null); + } + } + catch (error) { + throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createElement: (tagName) => { + try { + if (typeof window !== "undefined") { + return document.createElement(tagName); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createElement(tagName); + } + } + catch (error) { + throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createElementNS: (namespaceURI, qualifiedName) => { + try { + if (typeof window !== "undefined") { + return document.createElementNS(namespaceURI, qualifiedName); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createElementNS(namespaceURI, qualifiedName); + } + } + catch (error) { + throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createTextNode: (data) => { + try { + if (typeof window !== "undefined") { + return document.createTextNode(data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createTextNode(data); + } + } + catch (error) { + throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createCDATASection: (data) => { + try { + // For browser compatibility, use document.implementation to create CDATA + if (typeof window !== "undefined") { + const doc = document.implementation.createDocument(null, null, null); + return doc.createCDATASection(data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createCDATASection(data); + } + } + catch (error) { + throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createComment: (data) => { + try { + if (typeof window !== "undefined") { + return document.createComment(data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createComment(data); + } + } + catch (error) { + throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createProcessingInstruction: (target, data) => { + try { + if (typeof window !== "undefined") { + const doc = document.implementation.createDocument(null, null, null); + return doc.createProcessingInstruction(target, data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createProcessingInstruction(target, data); + } + } + catch (error) { + throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`); + } + }, + // New helper methods + /** + * Creates a proper namespace qualified attribute + */ + setNamespacedAttribute: (element, namespaceURI, qualifiedName, value) => { + try { + if (namespaceURI) { + element.setAttributeNS(namespaceURI, qualifiedName, value); + } + else { + element.setAttribute(qualifiedName, value); + } + } + catch (error) { + throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`); + } + }, + /** + * Check if an object is a DOM node + */ + isNode: (obj) => { + try { + return obj && typeof obj === 'object' && typeof obj.nodeType === 'number'; + } + catch (error) { + return false; + } + }, + /** + * Get DOM node type as string for debugging + */ + getNodeTypeName: (nodeType) => { + switch (nodeType) { + case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE'; + case nodeTypes.TEXT_NODE: return 'TEXT_NODE'; + case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE'; + case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE'; + case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE'; + default: return `UNKNOWN_NODE_TYPE(${nodeType})`; + } + }, + /** + * Get all node attributes as an object + */ + getNodeAttributes: (node) => { + const result = {}; + for (let i = 0; i < node.attributes.length; i++) { + const attr = node.attributes[i]; + result[attr.name] = attr.value; + } + return result; + }, + // Cleanup method (mainly for JSDOM) + cleanup: () => { + if (jsdomInstance && typeof jsdomInstance.window.close === 'function') { + jsdomInstance.window.close(); + } + } + }; +})(); + +class JSONUtil { + /** + * Constructor for JSONUtil + * @param config Configuration options + */ + constructor(config) { + this.config = config; + } + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * Automatically traverses into children arrays and flattens results. + * + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns Retrieved value or fallback + */ + getPath(obj, path, fallback = undefined) { + const segments = path.split("."); + let current = obj; + for (const segment of segments) { + if (Array.isArray(current)) { + // Apply the segment to each array element and flatten results + const results = current + .map((item) => this.resolveSegment(item, segment)) + .flat() + .filter((v) => v !== undefined); + current = results.length > 0 ? results : undefined; + } + else { + current = this.resolveSegment(current, segment); + } + if (current === undefined) + return fallback; + } + // Collapse singleton arrays + if (Array.isArray(current) && current.length === 1) { + return current[0]; + } + return current !== undefined ? current : fallback; + } + /** + * Resolves a single path segment in the context of a JSON object. + * Falls back to searching children for matching keys. + * + * @param obj The current object + * @param segment The path segment to resolve + * @returns Resolved value or undefined + */ + resolveSegment(obj, segment) { + if (obj == null || typeof obj !== "object") + return undefined; + // Direct property access + if (segment in obj) { + return obj[segment]; + } + // Check if this is a special property name that matches the config + if (segment === this.config.propNames.value || + segment === this.config.propNames.children || + segment === this.config.propNames.attributes || + segment === this.config.propNames.namespace || + segment === this.config.propNames.prefix || + segment === this.config.propNames.cdata || + segment === this.config.propNames.comments || + segment === this.config.propNames.instruction || + segment === this.config.propNames.target) { + const configKey = Object.entries(this.config.propNames).find(([_, value]) => value === segment)?.[0]; + if (configKey && obj[segment] !== undefined) { + return obj[segment]; + } + } + // Check children for objects that contain the segment + const childrenKey = this.config.propNames.children; + const children = obj[childrenKey]; + if (Array.isArray(children)) { + const matches = children + .map((child) => (segment in child ? child[segment] : undefined)) + .filter((v) => v !== undefined); + return matches.length > 0 ? matches : undefined; + } + return undefined; + } + /** + * Converts a plain JSON object to the XML-like JSON structure. + * Optionally wraps the result in a root element with attributes and namespaces. + * + * @param obj Standard JSON object + * @param root Optional root element configuration (either a string or object with $ keys) + * @returns XML-like JSON object + */ + fromJSONObject(obj, root) { + const wrappedObject = this.wrapObject(obj); + if (typeof root === "string") { + // Root is a simple string: wrap result with this root tag + return { [root]: wrappedObject }; + } + if (root && typeof root === "object") { + // Handle root with config-based keys + const elementName = root.name || "root"; // Default to "root" if no name is provided + const prefix = root[this.config.propNames.prefix] || ""; + const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName; + const result = { + [qualifiedName]: {}, + }; + // Add attributes to the root element if defined + const attrsKey = this.config.propNames.attributes; + if (root[attrsKey] && Array.isArray(root[attrsKey])) { + result[qualifiedName][attrsKey] = root[attrsKey]; + } + // Merge existing children with the new generated children + const childrenKey = this.config.propNames.children; + const children = root[childrenKey] ? root[childrenKey] : []; + result[qualifiedName][childrenKey] = [ + ...children, + { [elementName]: wrappedObject }, + ]; + // Add namespace and prefix if defined + const nsKey = this.config.propNames.namespace; + if (root[nsKey]) { + result[qualifiedName][nsKey] = root[nsKey]; + } + if (prefix && root[nsKey]) { + result[qualifiedName][`xmlns:${prefix}`] = root[nsKey]; + } + return result; + } + // Default behavior if no root is provided + return wrappedObject; + } + /** + * Wraps a standard JSON value in the XML-like JSON structure + * @param value Value to wrap + * @returns Wrapped value + */ + wrapObject(value) { + const valKey = this.config.propNames.value; + const childrenKey = this.config.propNames.children; + if (value === null || + typeof value === "string" || + typeof value === "number" || + typeof value === "boolean") { + return { [valKey]: value }; + } + if (Array.isArray(value)) { + // For arrays, wrap each item and return as a children-style array of repeated elements + return { + [childrenKey]: value.map((item) => { + return this.wrapObject(item); + }), + }; + } + if (typeof value === "object") { + // It's an object: wrap its properties in children + const children = Object.entries(value).map(([key, val]) => ({ + [key]: this.wrapObject(val), + })); + return { [childrenKey]: children }; + } + return undefined; // Fallback for unhandled types + } + /** + * Check if an object is empty + * @param value Value to check + * @returns true if empty + */ + isEmpty(value) { + if (value == null) + return true; + if (Array.isArray(value)) + return value.length === 0; + if (typeof value === "object") + return Object.keys(value).length === 0; + return false; + } + /** + * Safely stringify JSON for debugging + * @param obj Object to stringify + * @param indent Optional indentation level + * @returns JSON string representation + */ + safeStringify(obj, indent = 2) { + try { + return JSON.stringify(obj, null, indent); + } + catch (error) { + return "[Cannot stringify object]"; + } + } + /** + * Deep clone an object + * @param obj Object to clone + * @returns Cloned object + */ + deepClone(obj) { + try { + return JSON.parse(JSON.stringify(obj)); + } + catch (error) { + throw new Error(`Failed to deep clone object: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Deep merge two objects with proper type handling + * @param target Target object + * @param source Source object + * @returns Merged object (target is modified) + */ + deepMerge(target, source) { + if (!source || typeof source !== "object" || source === null) { + return target; + } + if (!target || typeof target !== "object" || target === null) { + return source; + } + Object.keys(source).forEach((key) => { + const sourceValue = source[key]; + const targetValue = target[key]; + // If both source and target values are objects, recursively merge them + if (sourceValue !== null && + targetValue !== null && + typeof sourceValue === "object" && + typeof targetValue === "object" && + !Array.isArray(sourceValue) && + !Array.isArray(targetValue)) { + // Recursively merge the nested objects + target[key] = this.deepMerge(targetValue, sourceValue); + } + else { + // Otherwise just replace the value + target[key] = sourceValue; + } + }); + return target; + } +} + +/** + * Utility for applying value transformations + */ +class TransformUtil { + /** + * Create a new TransformUtil + * @param config Configuration + */ + constructor(config) { + this.config = config; + } + /** + * Apply transforms to a value + * @param value Value to transform + * @param context Transformation context + * @returns Transformed value + */ + applyTransforms(value, context) { + // Skip transformation if no transformers are configured + if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) { + return value; + } + // Apply each transformer in sequence + let transformedValue = value; + for (const transformer of this.config.valueTransforms) { + transformedValue = transformer.process(transformedValue, context); + } + return transformedValue; + } + /** + * Create a transform context + * @param direction Direction of transformation + * @param nodeName Name of the current node + * @param nodeType DOM node type + * @param options Additional context options + * @returns Transform context + */ + createContext(direction, nodeName, nodeType, options = {}) { + return { + direction, + nodeName, + nodeType, + path: options.path || nodeName, + namespace: options.namespace, + prefix: options.prefix, + isAttribute: options.isAttribute || false, + attributeName: options.attributeName, + parent: options.parent, + config: this.config, + }; + } + /** + * Get a user-friendly node type name for debugging + * @param nodeType DOM node type + * @returns String representation of node type + */ + getNodeTypeName(nodeType) { + return DOMAdapter.getNodeTypeName(nodeType); + } +} + +/** + * XMLToJSON Parser for converting XML to JSON + */ +class XMLToJSON { + /** + * Constructor for XMLToJSON + * @param config Configuration options + */ + constructor(config) { + this.config = config; + this.jsonUtil = new JSONUtil(this.config); + this.transformUtil = new TransformUtil(this.config); + } + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + parse(xmlString) { + try { + const xmlDoc = DOMAdapter.parseFromString(xmlString, "text/xml"); + // Check for parsing errors + const errors = xmlDoc.getElementsByTagName("parsererror"); + if (errors.length > 0) { + throw new XJXError(`XML parsing error: ${errors[0].textContent}`); + } + return this.nodeToJson(xmlDoc.documentElement); + } + catch (error) { + throw new XJXError(`Failed to convert XML to JSON: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Convert a DOM node to JSON representation + * @param node DOM node to convert + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the XML tree + * @returns JSON representation of the node + */ + nodeToJson(node, parentContext, path = "") { + const result = {}; + // Handle element nodes + if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { + const element = node; + // Use localName instead of nodeName to strip namespace prefix + const nodeName = element.localName || + element.nodeName.split(":").pop() || + element.nodeName; + // Update the current path + const currentPath = path ? `${path}.${nodeName}` : nodeName; + const nodeObj = {}; + // Create context for this node + const context = this.transformUtil.createContext('xml-to-json', nodeName, node.nodeType, { + path: currentPath, + namespace: element.namespaceURI || undefined, + prefix: element.prefix || undefined, + parent: parentContext + }); + // Process namespaces if enabled + if (this.config.preserveNamespaces) { + const ns = element.namespaceURI; + if (ns) { + nodeObj[this.config.propNames.namespace] = ns; + } + const prefix = element.prefix; + if (prefix) { + nodeObj[this.config.propNames.prefix] = prefix; + } + } + // Process attributes if enabled + if (this.config.preserveAttributes && element.attributes.length > 0) { + const attrs = []; + for (let i = 0; i < element.attributes.length; i++) { + const attr = element.attributes[i]; + // Strip namespace prefix from attribute name + const attrLocalName = attr.localName || attr.name.split(":").pop() || attr.name; + // Create attribute context + const attrContext = this.transformUtil.createContext('xml-to-json', nodeName, node.nodeType, { + path: `${currentPath}.${attrLocalName}`, + namespace: attr.namespaceURI || undefined, + prefix: attr.prefix || undefined, + isAttribute: true, + attributeName: attrLocalName, + parent: context + }); + // Apply transformations to attribute value + const transformedValue = this.transformUtil.applyTransforms(attr.value, attrContext); + // Create attribute object with consistent structure + const attrObj = { + [attrLocalName]: { + [this.config.propNames.value]: transformedValue, + }, + }; + // Add namespace info for attribute if present and enabled + if (this.config.preserveNamespaces) { + // Handle attribute namespace + if (attr.namespaceURI) { + attrObj[attrLocalName][this.config.propNames.namespace] = + attr.namespaceURI; + } + // Handle attribute prefix + if (attr.prefix) { + attrObj[attrLocalName][this.config.propNames.prefix] = + attr.prefix; + } + } + attrs.push(attrObj); + } + if (attrs.length > 0) { + nodeObj[this.config.propNames.attributes] = attrs; + } + } + // Process child nodes + if (element.childNodes.length > 0) { + const children = []; + const childrenKey = this.config.propNames.children; + const valueKey = this.config.propNames.value; + const cdataKey = this.config.propNames.cdata; + const commentsKey = this.config.propNames.comments; + const instructionKey = this.config.propNames.instruction; + const targetKey = this.config.propNames.target; + for (let i = 0; i < element.childNodes.length; i++) { + const child = element.childNodes[i]; + // Text nodes - only process if preserveTextNodes is true + if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) { + if (this.config.preserveTextNodes) { + let text = child.nodeValue || ""; + // Skip whitespace-only text nodes if whitespace preservation is disabled + if (!this.config.preserveWhitespace) { + if (text.trim() === "") { + continue; + } + // Trim the text when preserveWhitespace is false + text = text.trim(); + } + // Create text node context + const textContext = this.transformUtil.createContext('xml-to-json', '#text', child.nodeType, { + path: `${currentPath}.#text`, + parent: context + }); + // Apply transformations to text value + const transformedText = this.transformUtil.applyTransforms(text, textContext); + children.push({ [valueKey]: transformedText }); + } + } + // CDATA sections + else if (child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE && + this.config.preserveCDATA) { + // Create CDATA context + const cdataContext = this.transformUtil.createContext('xml-to-json', '#cdata', child.nodeType, { + path: `${currentPath}.#cdata`, + parent: context + }); + // Apply transformations to CDATA value + const transformedCData = this.transformUtil.applyTransforms(child.nodeValue || "", cdataContext); + children.push({ + [cdataKey]: transformedCData, + }); + } + // Comments + else if (child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE && + this.config.preserveComments) { + children.push({ + [commentsKey]: child.nodeValue || "", + }); + } + // Processing instructions + else if (child.nodeType === + DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE && + this.config.preserveProcessingInstr) { + children.push({ + [instructionKey]: { + [targetKey]: child.nodeName, + [valueKey]: child.nodeValue || "", + }, + }); + } + // Element nodes (recursive) + else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { + children.push(this.nodeToJson(child, context, currentPath)); + } + } + if (children.length > 0) { + nodeObj[childrenKey] = children; + } + } + // Apply compact option - remove empty properties if enabled + if (this.config.outputOptions.compact) { + Object.keys(nodeObj).forEach((key) => { + const cleaned = this.cleanNode(nodeObj[key]); + if (cleaned === undefined) { + delete nodeObj[key]; + } + else { + nodeObj[key] = cleaned; + } + }); + } + result[nodeName] = nodeObj; + } + return result; + } + cleanNode(node) { + if (Array.isArray(node)) { + // Clean each item in the array and filter out empty ones + const cleanedArray = node + .map((item) => this.cleanNode(item)) + .filter((item) => { + return !(item === null || + item === undefined || + (typeof item === "object" && Object.keys(item).length === 0)); + }); + return cleanedArray.length > 0 ? cleanedArray : undefined; + } + else if (typeof node === "object" && node !== null) { + // Clean properties recursively + Object.keys(node).forEach((key) => { + const cleanedChild = this.cleanNode(node[key]); + if (cleanedChild === null || + cleanedChild === undefined || + (Array.isArray(cleanedChild) && cleanedChild.length === 0) || + (typeof cleanedChild === "object" && + Object.keys(cleanedChild).length === 0)) { + delete node[key]; + } + else { + node[key] = cleanedChild; + } + }); + // Handle the special case for nodes with only empty children/attributes + const childrenKey = this.config.propNames.children; + const attrsKey = this.config.propNames.attributes; + const keys = Object.keys(node); + if (keys.every((key) => key === childrenKey || key === attrsKey) && + (node[childrenKey] === undefined || + this.jsonUtil.isEmpty(node[childrenKey])) && + (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))) { + return undefined; + } + return Object.keys(node).length > 0 ? node : undefined; + } + return node; + } +} + +/** + * XMLUtil - Utility functions for XML processing + */ +class XMLUtil { + /** + * Constructor for XMLUtil + * @param config Configuration options + */ + constructor(config) { + this.config = config; + } + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + prettyPrintXml(xmlString) { + const indent = this.config.outputOptions.indent; + const INDENT = " ".repeat(indent); + try { + const doc = DOMAdapter.parseFromString(xmlString, "text/xml"); + const serializer = (node, level = 0) => { + const pad = INDENT.repeat(level); + switch (node.nodeType) { + case DOMAdapter.nodeTypes.ELEMENT_NODE: { + const el = node; + const tagName = el.tagName; + const attrs = Array.from(el.attributes) + .map((a) => `${a.name}="${a.value}"`) + .join(" "); + const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`; + const children = Array.from(el.childNodes); + if (children.length === 0) { + return `${pad}${openTag.replace(/>$/, " />")}\n`; + } + // Single text node: print inline + if (children.length === 0 || + (children.length === 1 && + children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE && + children[0].textContent?.trim() === "")) { + // Empty or whitespace-only + return `${pad}<${tagName}${attrs ? " " + attrs : ""}>\n`; + } + const inner = children + .map((child) => serializer(child, level + 1)) + .join(""); + return `${pad}${openTag}\n${inner}${pad}\n`; + } + case DOMAdapter.nodeTypes.TEXT_NODE: { + const text = node.textContent?.trim(); + return text ? `${pad}${text}\n` : ""; + } + case DOMAdapter.nodeTypes.CDATA_SECTION_NODE: + return `${pad}\n`; + case DOMAdapter.nodeTypes.COMMENT_NODE: + return `${pad}\n`; + case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE: + const pi = node; + return `${pad}\n`; + case DOMAdapter.nodeTypes.DOCUMENT_NODE: + return Array.from(node.childNodes) + .map((child) => serializer(child, level)) + .join(""); + default: + return ""; + } + }; + return serializer(doc).trim(); + } + catch (error) { + throw new XJXError(`Failed to pretty print XML: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Check if XML string is well-formed + * @param xmlString XML string to validate + * @returns Object with validation result and any error messages + */ + validateXML(xmlString) { + try { + const doc = DOMAdapter.parseFromString(xmlString, "text/xml"); + const errors = doc.getElementsByTagName("parsererror"); + if (errors.length > 0) { + return { + isValid: false, + message: errors[0].textContent || "Unknown parsing error", + }; + } + return { isValid: true }; + } + catch (error) { + return { + isValid: false, + message: error instanceof Error ? error.message : String(error), + }; + } + } + /** + * Add XML declaration to a string if missing + * @param xmlString XML string + * @returns XML string with declaration + */ + ensureXMLDeclaration(xmlString) { + if (!xmlString.trim().startsWith("\n' + xmlString; + } + return xmlString; + } + /** + * Escapes special characters in text for safe XML usage. + * @param text Text to escape. + * @returns Escaped XML string. + */ + escapeXML(text) { + if (typeof text !== "string" || text.length === 0) { + return ""; + } + return text.replace(/[&<>"']/g, (char) => { + switch (char) { + case "&": + return "&"; + case "<": + return "<"; + case ">": + return ">"; + case '"': + return """; + case "'": + return "'"; + default: + return char; + } + }); + } + /** + * Unescapes XML entities back to their character equivalents. + * @param text Text with XML entities. + * @returns Unescaped text. + */ + unescapeXML(text) { + if (typeof text !== "string" || text.length === 0) { + return ""; + } + return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => { + switch (entity) { + case "amp": + return "&"; + case "lt": + return "<"; + case "gt": + return ">"; + case "quot": + return '"'; + case "apos": + return "'"; + default: + return match; + } + }); + } + /** + * Extract the namespace prefix from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Prefix or null if no prefix + */ + extractPrefix(qualifiedName) { + const colonIndex = qualifiedName.indexOf(":"); + return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null; + } + /** + * Extract the local name from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Local name + */ + extractLocalName(qualifiedName) { + const colonIndex = qualifiedName.indexOf(":"); + return colonIndex > 0 + ? qualifiedName.substring(colonIndex + 1) + : qualifiedName; + } + /** + * Create a qualified name from prefix and local name + * @param prefix Namespace prefix (can be null) + * @param localName Local name + * @returns Qualified name + */ + createQualifiedName(prefix, localName) { + return prefix ? `${prefix}:${localName}` : localName; + } +} + +/** + * JSONToXML for converting JSON to XML + */ +class JSONToXML { + /** + * Constructor for JSONToXML + * @param config Configuration options + */ + constructor(config) { + this.config = config; + this.xmlUtil = new XMLUtil(this.config); + this.transformUtil = new TransformUtil(this.config); + } + /** + * Convert JSON object to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + serialize(jsonObj) { + try { + const doc = DOMAdapter.createDocument(); + const rootElement = this.jsonToNode(jsonObj, doc); + if (rootElement) { + // Handle the temporary root element if it exists + if (doc.documentElement && doc.documentElement.nodeName === "temp") { + doc.replaceChild(rootElement, doc.documentElement); + } + else { + doc.appendChild(rootElement); + } + } + // Add XML declaration if specified + let xmlString = DOMAdapter.serializeToString(doc); + // remove xhtml decl inserted by dom + xmlString = xmlString.replace(' xmlns="http://www.w3.org/1999/xhtml"', ''); + if (this.config.outputOptions.xml.declaration) { + xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString); + } + // Apply pretty printing if enabled + if (this.config.outputOptions.prettyPrint) { + xmlString = this.xmlUtil.prettyPrintXml(xmlString); + } + return xmlString; + } + catch (error) { + throw new XJXError(`Failed to convert JSON to XML: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Convert JSON object to DOM node + * @param jsonObj JSON object to convert + * @param doc Document for creating elements + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the JSON object + * @returns DOM Element + */ + jsonToNode(jsonObj, doc, parentContext, path = "") { + if (!jsonObj || typeof jsonObj !== "object") { + return null; + } + // Get the node name (first key in the object) + const nodeName = Object.keys(jsonObj)[0]; + if (!nodeName) { + return null; + } + const nodeData = jsonObj[nodeName]; + // Update the current path + const currentPath = path ? `${path}.${nodeName}` : nodeName; + // Create element with namespace if available + let element; + const namespaceKey = this.config.propNames.namespace; + const prefixKey = this.config.propNames.prefix; + const ns = nodeData[namespaceKey]; + const prefix = nodeData[prefixKey]; + // Create context for this node + const context = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.ELEMENT_NODE, { + path: currentPath, + namespace: ns, + prefix: prefix, + parent: parentContext + }); + if (ns && this.config.preserveNamespaces) { + if (prefix) { + // Create element with namespace and prefix + element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`); + } + else { + // Create element with namespace but no prefix + element = DOMAdapter.createElementNS(ns, nodeName); + } + } + else { + // Create element without namespace + element = DOMAdapter.createElement(nodeName); + } + // Process attributes if enabled + const attributesKey = this.config.propNames.attributes; + const valueKey = this.config.propNames.value; + if (this.config.preserveAttributes && + nodeData[attributesKey] && + Array.isArray(nodeData[attributesKey])) { + nodeData[attributesKey].forEach((attrObj) => { + const attrName = Object.keys(attrObj)[0]; + if (!attrName) + return; + const attrData = attrObj[attrName]; + // Create attribute context + const attrContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.ELEMENT_NODE, { + path: `${currentPath}.${attrName}`, + namespace: attrData[namespaceKey], + prefix: attrData[prefixKey], + isAttribute: true, + attributeName: attrName, + parent: context + }); + // Apply transformations to attribute value + const transformedValue = this.transformUtil.applyTransforms(attrData[valueKey] || "", attrContext); + const attrNs = attrData[namespaceKey]; + const attrPrefix = attrData[prefixKey]; + // Form qualified name for attribute if it has a prefix + let qualifiedName = attrName; + if (attrPrefix && this.config.preserveNamespaces) { + qualifiedName = `${attrPrefix}:${attrName}`; + } + DOMAdapter.setNamespacedAttribute(element, (attrNs && this.config.preserveNamespaces) ? attrNs : null, qualifiedName, transformedValue); + }); + } + // Process simple text value + if (nodeData[valueKey] !== undefined) { + // Apply transformations to text value + const textContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.TEXT_NODE, { + path: `${currentPath}.#text`, + namespace: ns, + prefix: prefix, + parent: context + }); + const transformedValue = this.transformUtil.applyTransforms(nodeData[valueKey], textContext); + element.textContent = transformedValue; + } + // Process children + const childrenKey = this.config.propNames.children; + const cdataKey = this.config.propNames.cdata; + const commentsKey = this.config.propNames.comments; + const instructionKey = this.config.propNames.instruction; + const targetKey = this.config.propNames.target; + if (nodeData[childrenKey] && + Array.isArray(nodeData[childrenKey])) { + nodeData[childrenKey].forEach((child) => { + // Text nodes + if (child[valueKey] !== undefined && + this.config.preserveTextNodes) { + // Apply transformations to text node + const textContext = this.transformUtil.createContext('json-to-xml', '#text', DOMAdapter.nodeTypes.TEXT_NODE, { + path: `${currentPath}.#text`, + parent: context + }); + const transformedText = this.transformUtil.applyTransforms(child[valueKey], textContext); + element.appendChild(DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))); + } + // CDATA sections + else if (child[cdataKey] !== undefined && + this.config.preserveCDATA) { + // Apply transformations to CDATA + const cdataContext = this.transformUtil.createContext('json-to-xml', '#cdata', DOMAdapter.nodeTypes.CDATA_SECTION_NODE, { + path: `${currentPath}.#cdata`, + parent: context + }); + const transformedCData = this.transformUtil.applyTransforms(child[cdataKey], cdataContext); + element.appendChild(DOMAdapter.createCDATASection(transformedCData)); + } + // Comments + else if (child[commentsKey] !== undefined && + this.config.preserveComments) { + element.appendChild(DOMAdapter.createComment(child[commentsKey])); + } + // Processing instructions + else if (child[instructionKey] !== undefined && + this.config.preserveProcessingInstr) { + const piData = child[instructionKey]; + const target = piData[targetKey]; + const data = piData[valueKey] || ""; + if (target) { + element.appendChild(DOMAdapter.createProcessingInstruction(target, data)); + } + } + // Element nodes (recursive) + else { + const childElement = this.jsonToNode(child, doc, context, currentPath); + if (childElement) { + element.appendChild(childElement); + } + } + }); + } + return element; + } +} + +/** + * Default configuration + */ +const DEFAULT_CONFIG = { + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveWhitespace: false, + preserveAttributes: true, + outputOptions: { + prettyPrint: true, + indent: 2, + compact: true, + json: {}, + xml: { + declaration: true, + }, + }, + propNames: { + namespace: "$ns", + prefix: "$pre", + attributes: "$attr", + value: "$val", + cdata: "$cdata", + comments: "$cmnt", + instruction: "$pi", + target: "$trgt", + children: "$children", + }, +}; + +/** + * XJX - Facade class for XML-JSON conversion operations + */ +class XJX { + /** + * Constructor for XJX utility + * @param config Configuration options + */ + constructor(config = {}) { + // First create a jsonUtil instance with default config to use its methods + this.jsonUtil = new JSONUtil(DEFAULT_CONFIG); + // Create a deep clone of the default config + const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG); + // Deep merge with the provided config + this.config = this.jsonUtil.deepMerge(defaultClone, config); + // Re-initialize jsonUtil with the merged config + this.jsonUtil = new JSONUtil(this.config); + // Initialize other components + this.xmlUtil = new XMLUtil(this.config); + this.xmltojson = new XMLToJSON(this.config); + this.jsontoxml = new JSONToXML(this.config); + } + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + xmlToJson(xmlString) { + return this.xmltojson.parse(xmlString); + } + /** + * Convert JSON object back to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + jsonToXml(jsonObj) { + return this.jsontoxml.serialize(jsonObj); + } + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + prettyPrintXml(xmlString) { + return this.xmlUtil.prettyPrintXml(xmlString); + } + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns The value at the specified path or the fallback value + */ + getPath(obj, path, fallback = undefined) { + return this.jsonUtil.getPath(obj, path, fallback); + } + /** + * Validate XML string + * @param xmlString XML string to validate + * @returns Validation result + */ + validateXML(xmlString) { + return this.xmlUtil.validateXML(xmlString); + } + /** + * Add a value transformer to the configuration + * @param transformer Value transformer to add + * @returns This XJX instance for chaining + */ + addTransformer(transformer) { + if (!this.config.valueTransforms) { + this.config.valueTransforms = []; + } + this.config.valueTransforms.push(transformer); + return this; + } + /** + * Removes all value transformers from the configuration + * @returns This XJX instance for chaining + */ + clearTransformers() { + this.config.valueTransforms = []; + return this; + } + /** + * Clean up any resources + */ + cleanup() { + DOMAdapter.cleanup(); + } +} + +/** + * Abstract base class for value transformers + */ +class ValueTransformer { + /** + * Process a value, transforming it if applicable + * @param value Value to potentially transform + * @param context Context including direction and other information + * @returns Transformed value or original if not applicable + */ + process(value, context) { + if (context.direction === 'xml-to-json') { + return this.xmlToJson(value, context); + } + else { + return this.jsonToXml(value, context); + } + } + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + xmlToJson(value, context) { + // Default implementation returns original value + return value; + } + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + jsonToXml(value, context) { + // Default implementation returns original value + return value; + } +} + +// Import locally so you can use it below + +export { DEFAULT_CONFIG, ValueTransformer, XJX, XJXError, XJX as default }; +//# sourceMappingURL=index.js.map diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..39c4d5a --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../../src/core/types/errors.ts","../../src/core/DOMAdapter.ts","../../src/core/utils/JsonUtils.ts","../../src/core/transforms/TransformUtil.ts","../../src/core/XmlToJsonConverter.ts","../../src/core/utils/XmlUtils.ts","../../src/core/JsonToXmlConverter.ts","../../src/core/config/config.ts","../../src/XJX.ts","../../src/core/transforms/ValueTransformer.ts","../../src/index.ts"],"sourcesContent":["/**\n * Error classes for the XJX library\n */\n\n/**\n * Base error class\n */\nexport class XJXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'XMLToJSONError';\n }\n}\n\n/**\n * Error for XML parsing issues\n */\nexport class XMLParseError extends XJXError {\n constructor(message: string) {\n super(`XML parse error: ${message}`);\n this.name = 'XMLParseError';\n }\n}\n\n/**\n * Error for XML serialization issues\n */\nexport class XMLSerializeError extends XJXError {\n constructor(message: string) {\n super(`XML serialize error: ${message}`);\n this.name = 'XMLSerializeError';\n }\n}\n\n/**\n * Error for environment incompatibility\n */\nexport class EnvironmentError extends XJXError {\n constructor(message: string) {\n super(`Environment error: ${message}`);\n this.name = 'EnvironmentError';\n }\n}\n\n/**\n * Error for invalid configuration\n */\nexport class ConfigurationError extends XJXError {\n constructor(message: string) {\n super(`Configuration error: ${message}`);\n this.name = 'ConfigurationError';\n }\n}","/**\n * DOM Environment provider with unified interface for browser and Node.js\n */\nimport { XJXError } from './types/errors';\n\ninterface NodeTypes {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n}\n\ninterface DOMWindow {\n DOMParser: any;\n XMLSerializer: any;\n Node: {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n };\n document: Document;\n close?: () => void; \n}\n\ninterface JSDOMInstance {\n window: DOMWindow;\n}\n\nexport const DOMAdapter = (() => {\n // Environment-specific DOM implementation\n let domParser: any;\n let xmlSerializer: any;\n let nodeTypes: NodeTypes;\n let docImplementation: any;\n let jsdomInstance: JSDOMInstance | null = null;\n\n try {\n if (typeof window === \"undefined\") {\n // Node.js environment - try JSDOM first\n try {\n const { JSDOM } = require(\"jsdom\");\n jsdomInstance = new JSDOM(\"\", {\n contentType: \"text/xml\",\n }) as JSDOMInstance;\n\n domParser = jsdomInstance.window.DOMParser;\n xmlSerializer = jsdomInstance.window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE,\n TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE,\n CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE,\n COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line\n };\n docImplementation = jsdomInstance.window.document.implementation;\n } catch (jsdomError) {\n // Fall back to xmldom if JSDOM isn't available\n try {\n const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom');\n domParser = DOMParser;\n xmlSerializer = XMLSerializer;\n // Standard DOM node types\n nodeTypes = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n CDATA_SECTION_NODE: 4,\n COMMENT_NODE: 8,\n PROCESSING_INSTRUCTION_NODE: 7,\n DOCUMENT_NODE: 9, \n };\n const implementation = new DOMImplementation();\n docImplementation = implementation;\n } catch (xmldomError) {\n throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`);\n }\n }\n } else {\n // Browser environment\n if (!window.DOMParser) {\n throw new XJXError(\"DOMParser is not available in this environment\");\n }\n\n if (!window.XMLSerializer) {\n throw new XJXError(\"XMLSerializer is not available in this environment\");\n }\n\n domParser = window.DOMParser;\n xmlSerializer = window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: Node.ELEMENT_NODE,\n TEXT_NODE: Node.TEXT_NODE,\n CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE,\n COMMENT_NODE: Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: Node.DOCUMENT_NODE, \n };\n docImplementation = document.implementation;\n }\n } catch (error) {\n throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n return {\n createParser: () => {\n try {\n return new domParser();\n } catch (error) {\n throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createSerializer: () => {\n try {\n return new xmlSerializer();\n } catch (error) {\n throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n nodeTypes,\n \n parseFromString: (xmlString: string, contentType: string = 'text/xml') => {\n try {\n const parser = new domParser();\n return parser.parseFromString(xmlString, contentType);\n } catch (error) {\n throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n serializeToString: (node: Node) => {\n try {\n const serializer = new xmlSerializer();\n return serializer.serializeToString(node);\n } catch (error) {\n throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createDocument: () => {\n try {\n // For browsers, create a document with a root element to avoid issues\n if (typeof window !== \"undefined\") {\n const parser = new domParser();\n return parser.parseFromString('', 'text/xml');\n } else {\n return docImplementation.createDocument(null, null, null);\n }\n } catch (error) {\n throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElement: (tagName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElement(tagName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElement(tagName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElementNS: (namespaceURI: string, qualifiedName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElementNS(namespaceURI, qualifiedName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElementNS(namespaceURI, qualifiedName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createTextNode: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createTextNode(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createTextNode(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createCDATASection: (data: string) => {\n try {\n // For browser compatibility, use document.implementation to create CDATA\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createComment: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createComment(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createComment(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createProcessingInstruction: (target: string, data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n // New helper methods\n \n /**\n * Creates a proper namespace qualified attribute\n */\n setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => {\n try {\n if (namespaceURI) {\n element.setAttributeNS(namespaceURI, qualifiedName, value);\n } else {\n element.setAttribute(qualifiedName, value);\n }\n } catch (error) {\n throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n /**\n * Check if an object is a DOM node\n */\n isNode: (obj: any): boolean => {\n try {\n return obj && typeof obj === 'object' && typeof obj.nodeType === 'number';\n } catch (error) {\n return false;\n }\n },\n \n /**\n * Get DOM node type as string for debugging\n */\n getNodeTypeName: (nodeType: number): string => {\n switch (nodeType) {\n case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE';\n case nodeTypes.TEXT_NODE: return 'TEXT_NODE';\n case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE';\n case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE';\n case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE';\n default: return `UNKNOWN_NODE_TYPE(${nodeType})`;\n }\n },\n \n /**\n * Get all node attributes as an object\n */\n getNodeAttributes: (node: Element): Record => {\n const result: Record = {};\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n result[attr.name] = attr.value;\n }\n return result;\n },\n \n // Cleanup method (mainly for JSDOM)\n cleanup: () => {\n if (jsdomInstance && typeof jsdomInstance.window.close === 'function') {\n jsdomInstance.window.close();\n }\n }\n };\n})();","/**\n * JSONUtil - Utility functions for JSON processing\n */\nimport { Configuration } from \"../types/types\";\n\nexport class JSONUtil {\n private config: Configuration;\n\n /**\n * Constructor for JSONUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * Automatically traverses into children arrays and flattens results.\n *\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns Retrieved value or fallback\n */\n getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n const segments = path.split(\".\");\n let current: any = obj;\n\n for (const segment of segments) {\n if (Array.isArray(current)) {\n // Apply the segment to each array element and flatten results\n const results = current\n .map((item) => this.resolveSegment(item, segment))\n .flat()\n .filter((v) => v !== undefined);\n current = results.length > 0 ? results : undefined;\n } else {\n current = this.resolveSegment(current, segment);\n }\n\n if (current === undefined) return fallback;\n }\n\n // Collapse singleton arrays\n if (Array.isArray(current) && current.length === 1) {\n return current[0];\n }\n\n return current !== undefined ? current : fallback;\n }\n\n /**\n * Resolves a single path segment in the context of a JSON object.\n * Falls back to searching children for matching keys.\n *\n * @param obj The current object\n * @param segment The path segment to resolve\n * @returns Resolved value or undefined\n */\n private resolveSegment(obj: any, segment: string): any {\n if (obj == null || typeof obj !== \"object\") return undefined;\n\n // Direct property access\n if (segment in obj) {\n return obj[segment];\n }\n\n // Check if this is a special property name that matches the config\n if (\n segment === this.config.propNames.value ||\n segment === this.config.propNames.children ||\n segment === this.config.propNames.attributes ||\n segment === this.config.propNames.namespace ||\n segment === this.config.propNames.prefix ||\n segment === this.config.propNames.cdata ||\n segment === this.config.propNames.comments ||\n segment === this.config.propNames.instruction ||\n segment === this.config.propNames.target\n ) {\n const configKey = Object.entries(this.config.propNames).find(\n ([_, value]) => value === segment\n )?.[0];\n\n if (configKey && obj[segment] !== undefined) {\n return obj[segment];\n }\n }\n\n // Check children for objects that contain the segment\n const childrenKey = this.config.propNames.children;\n const children = obj[childrenKey];\n if (Array.isArray(children)) {\n const matches = children\n .map((child) => (segment in child ? child[segment] : undefined))\n .filter((v) => v !== undefined);\n return matches.length > 0 ? matches : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Converts a plain JSON object to the XML-like JSON structure.\n * Optionally wraps the result in a root element with attributes and namespaces.\n *\n * @param obj Standard JSON object\n * @param root Optional root element configuration (either a string or object with $ keys)\n * @returns XML-like JSON object\n */\n fromJSONObject(obj: any, root?: any): any {\n const wrappedObject = this.wrapObject(obj);\n\n if (typeof root === \"string\") {\n // Root is a simple string: wrap result with this root tag\n return { [root]: wrappedObject };\n }\n\n if (root && typeof root === \"object\") {\n // Handle root with config-based keys\n const elementName = root.name || \"root\"; // Default to \"root\" if no name is provided\n const prefix = root[this.config.propNames.prefix] || \"\";\n const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName;\n\n const result: any = {\n [qualifiedName]: {},\n };\n\n // Add attributes to the root element if defined\n const attrsKey = this.config.propNames.attributes;\n if (root[attrsKey] && Array.isArray(root[attrsKey])) {\n result[qualifiedName][attrsKey] = root[attrsKey];\n }\n\n // Merge existing children with the new generated children\n const childrenKey = this.config.propNames.children;\n const children = root[childrenKey] ? root[childrenKey] : [];\n result[qualifiedName][childrenKey] = [\n ...children,\n { [elementName]: wrappedObject },\n ];\n\n // Add namespace and prefix if defined\n const nsKey = this.config.propNames.namespace;\n if (root[nsKey]) {\n result[qualifiedName][nsKey] = root[nsKey];\n }\n\n if (prefix && root[nsKey]) {\n result[qualifiedName][`xmlns:${prefix}`] = root[nsKey];\n }\n\n return result;\n }\n\n // Default behavior if no root is provided\n return wrappedObject;\n }\n\n /**\n * Wraps a standard JSON value in the XML-like JSON structure\n * @param value Value to wrap\n * @returns Wrapped value\n */\n private wrapObject(value: any): any {\n const valKey = this.config.propNames.value;\n const childrenKey = this.config.propNames.children;\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return { [valKey]: value };\n }\n\n if (Array.isArray(value)) {\n // For arrays, wrap each item and return as a children-style array of repeated elements\n return {\n [childrenKey]: value.map((item) => {\n return this.wrapObject(item);\n }),\n };\n }\n\n if (typeof value === \"object\") {\n // It's an object: wrap its properties in children\n const children = Object.entries(value).map(([key, val]) => ({\n [key]: this.wrapObject(val),\n }));\n\n return { [childrenKey]: children };\n }\n\n return undefined; // Fallback for unhandled types\n }\n\n /**\n * Check if an object is empty\n * @param value Value to check\n * @returns true if empty\n */\n isEmpty(value: any): boolean {\n if (value == null) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n }\n\n /**\n * Safely stringify JSON for debugging\n * @param obj Object to stringify\n * @param indent Optional indentation level\n * @returns JSON string representation\n */\n safeStringify(obj: any, indent: number = 2): string {\n try {\n return JSON.stringify(obj, null, indent);\n } catch (error) {\n return \"[Cannot stringify object]\";\n }\n }\n\n /**\n * Deep clone an object\n * @param obj Object to clone\n * @returns Cloned object\n */\n deepClone(obj: any): any {\n try {\n return JSON.parse(JSON.stringify(obj));\n } catch (error) {\n throw new Error(\n `Failed to deep clone object: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Deep merge two objects with proper type handling\n * @param target Target object\n * @param source Source object\n * @returns Merged object (target is modified)\n */\n deepMerge(target: T, source: Partial): T {\n if (!source || typeof source !== \"object\" || source === null) {\n return target;\n }\n\n if (!target || typeof target !== \"object\" || target === null) {\n return source as unknown as T;\n }\n\n Object.keys(source).forEach((key) => {\n const sourceValue = source[key as keyof Partial];\n const targetValue = target[key as keyof T];\n\n // If both source and target values are objects, recursively merge them\n if (\n sourceValue !== null &&\n targetValue !== null &&\n typeof sourceValue === \"object\" &&\n typeof targetValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n !Array.isArray(targetValue)\n ) {\n // Recursively merge the nested objects\n (target as any)[key] = this.deepMerge(targetValue, sourceValue as any);\n } else {\n // Otherwise just replace the value\n (target as any)[key] = sourceValue;\n }\n });\n\n return target;\n }\n}\n","/**\n * Utilities for applying value transformations\n */\nimport { Configuration } from '../types/types';\nimport { TransformContext, TransformDirection } from './ValueTransformer';\nimport { DOMAdapter } from '../DOMAdapter';\n\n/**\n * Utility for applying value transformations\n */\nexport class TransformUtil {\n private config: Configuration;\n\n /**\n * Create a new TransformUtil\n * @param config Configuration\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Apply transforms to a value\n * @param value Value to transform\n * @param context Transformation context\n * @returns Transformed value\n */\n applyTransforms(value: any, context: TransformContext): any {\n // Skip transformation if no transformers are configured\n if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) {\n return value;\n }\n\n // Apply each transformer in sequence\n let transformedValue = value;\n for (const transformer of this.config.valueTransforms) {\n transformedValue = transformer.process(transformedValue, context);\n }\n\n return transformedValue;\n }\n\n /**\n * Create a transform context\n * @param direction Direction of transformation\n * @param nodeName Name of the current node\n * @param nodeType DOM node type\n * @param options Additional context options\n * @returns Transform context\n */\n createContext(\n direction: TransformDirection,\n nodeName: string,\n nodeType: number,\n options: {\n path?: string;\n namespace?: string;\n prefix?: string;\n isAttribute?: boolean;\n attributeName?: string;\n parent?: TransformContext;\n } = {}\n ): TransformContext {\n return {\n direction,\n nodeName,\n nodeType,\n path: options.path || nodeName,\n namespace: options.namespace,\n prefix: options.prefix,\n isAttribute: options.isAttribute || false,\n attributeName: options.attributeName,\n parent: options.parent,\n config: this.config,\n };\n }\n\n /**\n * Get a user-friendly node type name for debugging\n * @param nodeType DOM node type\n * @returns String representation of node type\n */\n getNodeTypeName(nodeType: number): string {\n return DOMAdapter.getNodeTypeName(nodeType);\n }\n}","/**\n * XMLToJSON class for converting XML to JSON with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { JSONUtil } from \"./utils/JsonUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * XMLToJSON Parser for converting XML to JSON\n */\nexport class XMLToJSON {\n private config: Configuration;\n private jsonUtil: JSONUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for XMLToJSON\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.jsonUtil = new JSONUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public parse(xmlString: string): Record {\n try {\n const xmlDoc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n // Check for parsing errors\n const errors = xmlDoc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n throw new XJXError(`XML parsing error: ${errors[0].textContent}`);\n }\n\n return this.nodeToJson(xmlDoc.documentElement);\n } catch (error) {\n throw new XJXError(\n `Failed to convert XML to JSON: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert a DOM node to JSON representation\n * @param node DOM node to convert\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the XML tree\n * @returns JSON representation of the node\n */\n private nodeToJson(node: Node, parentContext?: TransformContext, path: string = \"\"): Record {\n const result: Record = {};\n\n // Handle element nodes\n if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n const element = node as Element;\n // Use localName instead of nodeName to strip namespace prefix\n const nodeName =\n element.localName ||\n element.nodeName.split(\":\").pop() ||\n element.nodeName;\n\n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n const nodeObj: Record = {};\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: currentPath,\n namespace: element.namespaceURI || undefined,\n prefix: element.prefix || undefined,\n parent: parentContext\n }\n );\n\n // Process namespaces if enabled\n if (this.config.preserveNamespaces) {\n const ns = element.namespaceURI;\n if (ns) {\n nodeObj[this.config.propNames.namespace] = ns;\n }\n\n const prefix = element.prefix;\n if (prefix) {\n nodeObj[this.config.propNames.prefix] = prefix;\n }\n }\n\n // Process attributes if enabled\n if (this.config.preserveAttributes && element.attributes.length > 0) {\n const attrs: Array> = [];\n\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n // Strip namespace prefix from attribute name\n const attrLocalName =\n attr.localName || attr.name.split(\":\").pop() || attr.name;\n\n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: `${currentPath}.${attrLocalName}`,\n namespace: attr.namespaceURI || undefined,\n prefix: attr.prefix || undefined,\n isAttribute: true,\n attributeName: attrLocalName,\n parent: context\n }\n );\n\n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attr.value,\n attrContext\n );\n\n // Create attribute object with consistent structure\n const attrObj: Record = {\n [attrLocalName]: {\n [this.config.propNames.value]: transformedValue,\n },\n };\n\n // Add namespace info for attribute if present and enabled\n if (this.config.preserveNamespaces) {\n // Handle attribute namespace\n if (attr.namespaceURI) {\n attrObj[attrLocalName][this.config.propNames.namespace] =\n attr.namespaceURI;\n }\n\n // Handle attribute prefix\n if (attr.prefix) {\n attrObj[attrLocalName][this.config.propNames.prefix] =\n attr.prefix;\n }\n }\n\n attrs.push(attrObj);\n }\n\n if (attrs.length > 0) {\n nodeObj[this.config.propNames.attributes] = attrs;\n }\n }\n\n // Process child nodes\n if (element.childNodes.length > 0) {\n const children: Array> = [];\n const childrenKey = this.config.propNames.children;\n const valueKey = this.config.propNames.value;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n\n // Text nodes - only process if preserveTextNodes is true\n if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) {\n if (this.config.preserveTextNodes) {\n let text = child.nodeValue || \"\";\n\n // Skip whitespace-only text nodes if whitespace preservation is disabled\n if (!this.config.preserveWhitespace) {\n if (text.trim() === \"\") {\n continue;\n }\n // Trim the text when preserveWhitespace is false\n text = text.trim();\n }\n\n // Create text node context\n const textContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#text',\n child.nodeType,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n\n // Apply transformations to text value\n const transformedText = this.transformUtil.applyTransforms(\n text,\n textContext\n );\n\n children.push({ [valueKey]: transformedText });\n }\n }\n // CDATA sections\n else if (\n child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE &&\n this.config.preserveCDATA\n ) {\n // Create CDATA context\n const cdataContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#cdata',\n child.nodeType,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n\n // Apply transformations to CDATA value\n const transformedCData = this.transformUtil.applyTransforms(\n child.nodeValue || \"\",\n cdataContext\n );\n\n children.push({\n [cdataKey]: transformedCData,\n });\n }\n // Comments\n else if (\n child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE &&\n this.config.preserveComments\n ) {\n children.push({\n [commentsKey]: child.nodeValue || \"\",\n });\n }\n // Processing instructions\n else if (\n child.nodeType ===\n DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE &&\n this.config.preserveProcessingInstr\n ) {\n children.push({\n [instructionKey]: {\n [targetKey]: child.nodeName,\n [valueKey]: child.nodeValue || \"\",\n },\n });\n }\n // Element nodes (recursive)\n else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n children.push(this.nodeToJson(child, context, currentPath));\n }\n }\n\n if (children.length > 0) {\n nodeObj[childrenKey] = children;\n }\n }\n\n // Apply compact option - remove empty properties if enabled\n if (this.config.outputOptions.compact) {\n Object.keys(nodeObj).forEach((key) => {\n const cleaned = this.cleanNode(nodeObj[key]);\n if (cleaned === undefined) {\n delete nodeObj[key];\n } else {\n nodeObj[key] = cleaned;\n }\n });\n }\n\n result[nodeName] = nodeObj;\n }\n\n return result;\n }\n\n private cleanNode(node: any): any {\n if (Array.isArray(node)) {\n // Clean each item in the array and filter out empty ones\n const cleanedArray = node\n .map((item) => this.cleanNode(item))\n .filter((item) => {\n return !(\n item === null ||\n item === undefined ||\n (typeof item === \"object\" && Object.keys(item).length === 0)\n );\n });\n return cleanedArray.length > 0 ? cleanedArray : undefined;\n } else if (typeof node === \"object\" && node !== null) {\n // Clean properties recursively\n Object.keys(node).forEach((key) => {\n const cleanedChild = this.cleanNode(node[key]);\n if (\n cleanedChild === null ||\n cleanedChild === undefined ||\n (Array.isArray(cleanedChild) && cleanedChild.length === 0) ||\n (typeof cleanedChild === \"object\" &&\n Object.keys(cleanedChild).length === 0)\n ) {\n delete node[key];\n } else {\n node[key] = cleanedChild;\n }\n });\n\n // Handle the special case for nodes with only empty children/attributes\n const childrenKey = this.config.propNames.children;\n const attrsKey = this.config.propNames.attributes;\n const keys = Object.keys(node);\n if (\n keys.every((key) => key === childrenKey || key === attrsKey) &&\n (node[childrenKey] === undefined ||\n this.jsonUtil.isEmpty(node[childrenKey])) &&\n (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))\n ) {\n return undefined;\n }\n\n return Object.keys(node).length > 0 ? node : undefined;\n }\n\n return node;\n }\n}","/**\n * XMLUtil - Utility functions for XML processing\n */\nimport { XJXError } from \"../types/errors\";\nimport { DOMAdapter } from \"../DOMAdapter\";\nimport { Configuration } from \"../types/types\";\n\nexport class XMLUtil {\n private config: Configuration;\n\n /**\n * Constructor for XMLUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n prettyPrintXml(xmlString: string): string {\n const indent = this.config.outputOptions.indent;\n const INDENT = \" \".repeat(indent);\n\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n const serializer = (node: Node, level = 0): string => {\n const pad = INDENT.repeat(level);\n\n switch (node.nodeType) {\n case DOMAdapter.nodeTypes.ELEMENT_NODE: {\n const el = node as Element;\n const tagName = el.tagName;\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`;\n\n const children = Array.from(el.childNodes);\n\n if (children.length === 0) {\n return `${pad}${openTag.replace(/>$/, \" />\")}\\n`;\n }\n\n // Single text node: print inline\n if (\n children.length === 0 ||\n (children.length === 1 &&\n children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE &&\n children[0].textContent?.trim() === \"\")\n ) {\n // Empty or whitespace-only\n return `${pad}<${tagName}${attrs ? \" \" + attrs : \"\"}>\\n`;\n }\n\n const inner = children\n .map((child) => serializer(child, level + 1))\n .join(\"\");\n return `${pad}${openTag}\\n${inner}${pad}\\n`;\n }\n\n case DOMAdapter.nodeTypes.TEXT_NODE: {\n const text = node.textContent?.trim();\n return text ? `${pad}${text}\\n` : \"\";\n }\n\n case DOMAdapter.nodeTypes.CDATA_SECTION_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.COMMENT_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE:\n const pi = node as ProcessingInstruction;\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.DOCUMENT_NODE:\n return Array.from(node.childNodes)\n .map((child) => serializer(child, level))\n .join(\"\");\n\n default:\n return \"\";\n }\n };\n\n return serializer(doc).trim();\n } catch (error) {\n throw new XJXError(\n `Failed to pretty print XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Check if XML string is well-formed\n * @param xmlString XML string to validate\n * @returns Object with validation result and any error messages\n */\n validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n const errors = doc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n return {\n isValid: false,\n message: errors[0].textContent || \"Unknown parsing error\",\n };\n }\n return { isValid: true };\n } catch (error) {\n return {\n isValid: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Add XML declaration to a string if missing\n * @param xmlString XML string\n * @returns XML string with declaration\n */\n ensureXMLDeclaration(xmlString: string): string {\n if (!xmlString.trim().startsWith(\"\\n' + xmlString;\n }\n return xmlString;\n }\n\n /**\n * Escapes special characters in text for safe XML usage.\n * @param text Text to escape.\n * @returns Escaped XML string.\n */\n escapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&\";\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case '\"':\n return \""\";\n case \"'\":\n return \"'\";\n default:\n return char;\n }\n });\n }\n\n /**\n * Unescapes XML entities back to their character equivalents.\n * @param text Text with XML entities.\n * @returns Unescaped text.\n */\n unescapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => {\n switch (entity) {\n case \"amp\":\n return \"&\";\n case \"lt\":\n return \"<\";\n case \"gt\":\n return \">\";\n case \"quot\":\n return '\"';\n case \"apos\":\n return \"'\";\n default:\n return match;\n }\n });\n }\n\n /**\n * Extract the namespace prefix from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Prefix or null if no prefix\n */\n extractPrefix(qualifiedName: string): string | null {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null;\n }\n\n /**\n * Extract the local name from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Local name\n */\n extractLocalName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0\n ? qualifiedName.substring(colonIndex + 1)\n : qualifiedName;\n }\n\n /**\n * Create a qualified name from prefix and local name\n * @param prefix Namespace prefix (can be null)\n * @param localName Local name\n * @returns Qualified name\n */\n createQualifiedName(prefix: string | null, localName: string): string {\n return prefix ? `${prefix}:${localName}` : localName;\n }\n}","/**\n * JSONToXML class for converting JSON to XML with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { XMLUtil } from \"./utils/XmlUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * JSONToXML for converting JSON to XML\n */\nexport class JSONToXML {\n private config: Configuration;\n private xmlUtil: XMLUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for JSONToXML\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.xmlUtil = new XMLUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert JSON object to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public serialize(jsonObj: Record): string {\n try {\n const doc = DOMAdapter.createDocument();\n const rootElement = this.jsonToNode(jsonObj, doc);\n\n if (rootElement) {\n // Handle the temporary root element if it exists\n if (doc.documentElement && doc.documentElement.nodeName === \"temp\") {\n doc.replaceChild(rootElement, doc.documentElement);\n } else {\n doc.appendChild(rootElement);\n }\n }\n\n // Add XML declaration if specified\n let xmlString = DOMAdapter.serializeToString(doc);\n\n // remove xhtml decl inserted by dom\n xmlString = xmlString.replace(' xmlns=\"http://www.w3.org/1999/xhtml\"', '');\n\n if (this.config.outputOptions.xml.declaration) {\n xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString);\n }\n\n // Apply pretty printing if enabled\n if (this.config.outputOptions.prettyPrint) {\n xmlString = this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n return xmlString;\n } catch (error) {\n throw new XJXError(\n `Failed to convert JSON to XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert JSON object to DOM node\n * @param jsonObj JSON object to convert\n * @param doc Document for creating elements\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the JSON object\n * @returns DOM Element\n */\n private jsonToNode(\n jsonObj: Record,\n doc: Document,\n parentContext?: TransformContext,\n path: string = \"\"\n ): Element | null {\n if (!jsonObj || typeof jsonObj !== \"object\") {\n return null;\n }\n\n // Get the node name (first key in the object)\n const nodeName = Object.keys(jsonObj)[0];\n if (!nodeName) {\n return null;\n }\n\n const nodeData = jsonObj[nodeName];\n \n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n // Create element with namespace if available\n let element: Element;\n const namespaceKey = this.config.propNames.namespace;\n const prefixKey = this.config.propNames.prefix;\n const ns = nodeData[namespaceKey];\n const prefix = nodeData[prefixKey];\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: currentPath,\n namespace: ns,\n prefix: prefix,\n parent: parentContext\n }\n );\n\n if (ns && this.config.preserveNamespaces) {\n if (prefix) {\n // Create element with namespace and prefix\n element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`);\n } else {\n // Create element with namespace but no prefix\n element = DOMAdapter.createElementNS(ns, nodeName);\n }\n } else {\n // Create element without namespace\n element = DOMAdapter.createElement(nodeName);\n }\n\n // Process attributes if enabled\n const attributesKey = this.config.propNames.attributes;\n const valueKey = this.config.propNames.value;\n if (\n this.config.preserveAttributes &&\n nodeData[attributesKey] &&\n Array.isArray(nodeData[attributesKey])\n ) {\n nodeData[attributesKey].forEach(\n (attrObj: Record) => {\n const attrName = Object.keys(attrObj)[0];\n if (!attrName) return;\n\n const attrData = attrObj[attrName];\n \n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: `${currentPath}.${attrName}`,\n namespace: attrData[namespaceKey],\n prefix: attrData[prefixKey],\n isAttribute: true,\n attributeName: attrName,\n parent: context\n }\n );\n \n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attrData[valueKey] || \"\",\n attrContext\n );\n \n const attrNs = attrData[namespaceKey];\n const attrPrefix = attrData[prefixKey];\n\n // Form qualified name for attribute if it has a prefix\n let qualifiedName = attrName;\n if (attrPrefix && this.config.preserveNamespaces) {\n qualifiedName = `${attrPrefix}:${attrName}`;\n }\n\n DOMAdapter.setNamespacedAttribute(\n element, \n (attrNs && this.config.preserveNamespaces) ? attrNs : null, \n qualifiedName, \n transformedValue\n );\n }\n );\n }\n\n // Process simple text value\n if (nodeData[valueKey] !== undefined) {\n // Apply transformations to text value\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n namespace: ns,\n prefix: prefix,\n parent: context\n }\n );\n \n const transformedValue = this.transformUtil.applyTransforms(\n nodeData[valueKey],\n textContext\n );\n \n element.textContent = transformedValue;\n }\n\n // Process children\n const childrenKey = this.config.propNames.children;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n if (\n nodeData[childrenKey] &&\n Array.isArray(nodeData[childrenKey])\n ) {\n nodeData[childrenKey].forEach(\n (child: Record) => {\n // Text nodes\n if (\n child[valueKey] !== undefined &&\n this.config.preserveTextNodes\n ) {\n // Apply transformations to text node\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#text',\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n \n const transformedText = this.transformUtil.applyTransforms(\n child[valueKey],\n textContext\n );\n \n element.appendChild(\n DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))\n );\n }\n // CDATA sections\n else if (\n child[cdataKey] !== undefined &&\n this.config.preserveCDATA\n ) {\n // Apply transformations to CDATA\n const cdataContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#cdata',\n DOMAdapter.nodeTypes.CDATA_SECTION_NODE,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n \n const transformedCData = this.transformUtil.applyTransforms(\n child[cdataKey],\n cdataContext\n );\n \n element.appendChild(\n DOMAdapter.createCDATASection(\n transformedCData\n )\n );\n }\n // Comments\n else if (\n child[commentsKey] !== undefined &&\n this.config.preserveComments\n ) {\n element.appendChild(\n DOMAdapter.createComment(\n child[commentsKey]\n )\n );\n }\n // Processing instructions\n else if (\n child[instructionKey] !== undefined &&\n this.config.preserveProcessingInstr\n ) {\n const piData = child[instructionKey];\n const target = piData[targetKey];\n const data = piData[valueKey] || \"\";\n\n if (target) {\n element.appendChild(\n DOMAdapter.createProcessingInstruction(target, data)\n );\n }\n }\n // Element nodes (recursive)\n else {\n const childElement = this.jsonToNode(child, doc, context, currentPath);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n }\n );\n }\n\n return element;\n }\n}","/**\n * Default configuration for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: Configuration = {\n preserveNamespaces: true,\n preserveComments: true,\n preserveProcessingInstr: true,\n preserveCDATA: true,\n preserveTextNodes: true,\n preserveWhitespace: false,\n preserveAttributes: true,\n\n outputOptions: {\n prettyPrint: true,\n indent: 2,\n compact: true,\n json: {},\n xml: {\n declaration: true,\n },\n },\n\n propNames: {\n namespace: \"$ns\",\n prefix: \"$pre\",\n attributes: \"$attr\",\n value: \"$val\",\n cdata: \"$cdata\",\n comments: \"$cmnt\",\n instruction: \"$pi\", \n target: \"$trgt\", \n children: \"$children\",\n },\n};","/**\n * XJX - Facade class for XML-JSON conversion operations\n */\nimport { XMLToJSON } from \"./core/XmlToJsonConverter\";\nimport { JSONToXML } from \"./core/JsonToXmlConverter\";\nimport { Configuration } from \"./core/types/types\";\nimport { DEFAULT_CONFIG } from \"./core/config/config\";\nimport { DOMAdapter } from \"./core/DOMAdapter\";\nimport { XMLUtil } from \"./core/utils/XmlUtils\";\nimport { JSONUtil } from \"./core/utils/JsonUtils\";\nimport { ValueTransformer } from \"./core/transforms\";\n\nexport class XJX {\n private config: Configuration;\n private xmltojson: XMLToJSON;\n private jsontoxml: JSONToXML;\n private jsonUtil: JSONUtil;\n private xmlUtil: XMLUtil;\n\n /**\n * Constructor for XJX utility\n * @param config Configuration options\n */\n constructor(config: Partial = {}) {\n // First create a jsonUtil instance with default config to use its methods\n this.jsonUtil = new JSONUtil(DEFAULT_CONFIG);\n\n // Create a deep clone of the default config\n const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG);\n\n // Deep merge with the provided config\n this.config = this.jsonUtil.deepMerge(defaultClone, config);\n\n // Re-initialize jsonUtil with the merged config\n this.jsonUtil = new JSONUtil(this.config);\n\n // Initialize other components\n this.xmlUtil = new XMLUtil(this.config);\n this.xmltojson = new XMLToJSON(this.config);\n this.jsontoxml = new JSONToXML(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public xmlToJson(xmlString: string): Record {\n return this.xmltojson.parse(xmlString);\n }\n\n /**\n * Convert JSON object back to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public jsonToXml(jsonObj: Record): string {\n return this.jsontoxml.serialize(jsonObj);\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n public prettyPrintXml(xmlString: string): string {\n return this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns The value at the specified path or the fallback value\n */\n public getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n return this.jsonUtil.getPath(obj, path, fallback);\n }\n\n /**\n * Validate XML string\n * @param xmlString XML string to validate\n * @returns Validation result\n */\n public validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n return this.xmlUtil.validateXML(xmlString);\n }\n\n /**\n * Add a value transformer to the configuration\n * @param transformer Value transformer to add\n * @returns This XJX instance for chaining\n */\n public addTransformer(transformer: ValueTransformer): XJX {\n if (!this.config.valueTransforms) {\n this.config.valueTransforms = [];\n }\n this.config.valueTransforms.push(transformer);\n return this;\n }\n\n /**\n * Removes all value transformers from the configuration\n * @returns This XJX instance for chaining\n */\n public clearTransformers(): XJX {\n this.config.valueTransforms = [];\n return this;\n }\n\n /**\n * Clean up any resources\n */\n public cleanup(): void {\n DOMAdapter.cleanup();\n }\n}","/**\n * Value transformation types and base class for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Direction of the transformation\n */\nexport type TransformDirection = 'xml-to-json' | 'json-to-xml';\n\n/**\n * Context provided to value transformers\n */\nexport interface TransformContext {\n // Core transformation info\n direction: TransformDirection; // Direction of the current transformation\n \n // Node information\n nodeName: string; // Name of the current node\n nodeType: number; // DOM node type (element, text, etc.)\n namespace?: string; // Namespace URI if available\n prefix?: string; // Namespace prefix if available\n \n // Structure information\n path: string; // Dot-notation path to current node\n isAttribute: boolean; // Whether the current value is from an attribute\n attributeName?: string; // Name of attribute if isAttribute is true\n \n // Parent context (creates a chain)\n parent?: TransformContext; // Reference to parent context for traversal\n \n // Configuration reference\n config: Configuration; // Reference to the current configuration\n}\n\n/**\n * Abstract base class for value transformers\n */\nexport abstract class ValueTransformer {\n /**\n * Process a value, transforming it if applicable\n * @param value Value to potentially transform\n * @param context Context including direction and other information\n * @returns Transformed value or original if not applicable\n */\n process(value: any, context: TransformContext): any {\n if (context.direction === 'xml-to-json') {\n return this.xmlToJson(value, context);\n } else {\n return this.jsonToXml(value, context);\n }\n }\n\n /**\n * Transform a value from XML to JSON representation\n * @param value Value from XML\n * @param context Transformation context\n * @returns Transformed value for JSON\n */\n protected xmlToJson(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n\n /**\n * Transform a value from JSON to XML representation\n * @param value Value from JSON\n * @param context Transformation context\n * @returns Transformed value for XML\n */\n protected jsonToXml(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n}","// Import locally so you can use it below\nimport { XJX } from './XJX';\n\n// Core components\nexport { XJX };\nexport { Configuration } from './core/types/types';\nexport { DEFAULT_CONFIG } from './core/config/config';\n\n// Error handling\nexport { XJXError } from './core/types/errors';\n\n// Allow custom transformers\nexport { ValueTransformer } from './core/transforms/ValueTransformer';\n\n// Default export\nexport default XJX;"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/stats.html b/dist/stats.html new file mode 100644 index 0000000..8277f7f --- /dev/null +++ b/dist/stats.html @@ -0,0 +1,4949 @@ + + + + + + + + XJX Bundle Visualizer + + + +
+ + + + + diff --git a/dist/xjx.min.js b/dist/xjx.min.js new file mode 100644 index 0000000..1c8308f --- /dev/null +++ b/dist/xjx.min.js @@ -0,0 +1,2 @@ +var XJX=function(e){"use strict";class t extends Error{constructor(e){super(e),this.name="XMLToJSONError"}}const r=(()=>{let e,r,n,o,s=null;try{if("undefined"==typeof window)try{const{JSDOM:t}=require("jsdom");s=new t("",{contentType:"text/xml"}),e=s.window.DOMParser,r=s.window.XMLSerializer,n={ELEMENT_NODE:s.window.Node.ELEMENT_NODE,TEXT_NODE:s.window.Node.TEXT_NODE,CDATA_SECTION_NODE:s.window.Node.CDATA_SECTION_NODE,COMMENT_NODE:s.window.Node.COMMENT_NODE,PROCESSING_INSTRUCTION_NODE:s.window.Node.PROCESSING_INSTRUCTION_NODE,DOCUMENT_NODE:s.window.Node.DOCUMENT_NODE},o=s.window.document.implementation}catch(s){try{const{DOMParser:t,XMLSerializer:s,DOMImplementation:i}=require("@xmldom/xmldom");e=t,r=s,n={ELEMENT_NODE:1,TEXT_NODE:3,CDATA_SECTION_NODE:4,COMMENT_NODE:8,PROCESSING_INSTRUCTION_NODE:7,DOCUMENT_NODE:9};const a=new i;o=a}catch(e){throw new t("Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.")}}else{if(!window.DOMParser)throw new t("DOMParser is not available in this environment");if(!window.XMLSerializer)throw new t("XMLSerializer is not available in this environment");e=window.DOMParser,r=window.XMLSerializer,n={ELEMENT_NODE:Node.ELEMENT_NODE,TEXT_NODE:Node.TEXT_NODE,CDATA_SECTION_NODE:Node.CDATA_SECTION_NODE,COMMENT_NODE:Node.COMMENT_NODE,PROCESSING_INSTRUCTION_NODE:Node.PROCESSING_INSTRUCTION_NODE,DOCUMENT_NODE:Node.DOCUMENT_NODE},o=document.implementation}}catch(e){throw new t(`DOM environment initialization failed: ${e instanceof Error?e.message:String(e)}`)}return{createParser:()=>{try{return new e}catch(e){throw new t(`Failed to create DOM parser: ${e instanceof Error?e.message:String(e)}`)}},createSerializer:()=>{try{return new r}catch(e){throw new t(`Failed to create XML serializer: ${e instanceof Error?e.message:String(e)}`)}},nodeTypes:n,parseFromString:(r,n="text/xml")=>{try{return(new e).parseFromString(r,n)}catch(e){throw new t(`Failed to parse XML: ${e instanceof Error?e.message:String(e)}`)}},serializeToString:e=>{try{return(new r).serializeToString(e)}catch(e){throw new t(`Failed to serialize XML: ${e instanceof Error?e.message:String(e)}`)}},createDocument:()=>{try{if("undefined"!=typeof window){return(new e).parseFromString("","text/xml")}return o.createDocument(null,null,null)}catch(e){throw new t(`Failed to create document: ${e instanceof Error?e.message:String(e)}`)}},createElement:e=>{try{if("undefined"!=typeof window)return document.createElement(e);return o.createDocument(null,null,null).createElement(e)}catch(e){throw new t(`Failed to create element: ${e instanceof Error?e.message:String(e)}`)}},createElementNS:(e,r)=>{try{if("undefined"!=typeof window)return document.createElementNS(e,r);return o.createDocument(null,null,null).createElementNS(e,r)}catch(e){throw new t(`Failed to create element with namespace: ${e instanceof Error?e.message:String(e)}`)}},createTextNode:e=>{try{if("undefined"!=typeof window)return document.createTextNode(e);return o.createDocument(null,null,null).createTextNode(e)}catch(e){throw new t(`Failed to create text node: ${e instanceof Error?e.message:String(e)}`)}},createCDATASection:e=>{try{if("undefined"!=typeof window){return document.implementation.createDocument(null,null,null).createCDATASection(e)}return o.createDocument(null,null,null).createCDATASection(e)}catch(e){throw new t(`Failed to create CDATA section: ${e instanceof Error?e.message:String(e)}`)}},createComment:e=>{try{if("undefined"!=typeof window)return document.createComment(e);return o.createDocument(null,null,null).createComment(e)}catch(e){throw new t(`Failed to create comment: ${e instanceof Error?e.message:String(e)}`)}},createProcessingInstruction:(e,r)=>{try{if("undefined"!=typeof window){return document.implementation.createDocument(null,null,null).createProcessingInstruction(e,r)}return o.createDocument(null,null,null).createProcessingInstruction(e,r)}catch(e){throw new t(`Failed to create processing instruction: ${e instanceof Error?e.message:String(e)}`)}},setNamespacedAttribute:(e,r,n,o)=>{try{r?e.setAttributeNS(r,n,o):e.setAttribute(n,o)}catch(e){throw new t(`Failed to set attribute: ${e instanceof Error?e.message:String(e)}`)}},isNode:e=>{try{return e&&"object"==typeof e&&"number"==typeof e.nodeType}catch(e){return!1}},getNodeTypeName:e=>{switch(e){case n.ELEMENT_NODE:return"ELEMENT_NODE";case n.TEXT_NODE:return"TEXT_NODE";case n.CDATA_SECTION_NODE:return"CDATA_SECTION_NODE";case n.COMMENT_NODE:return"COMMENT_NODE";case n.PROCESSING_INSTRUCTION_NODE:return"PROCESSING_INSTRUCTION_NODE";default:return`UNKNOWN_NODE_TYPE(${e})`}},getNodeAttributes:e=>{const t={};for(let r=0;r{s&&"function"==typeof s.window.close&&s.window.close()}}})();class n{constructor(e){this.config=e}getPath(e,t,r=void 0){const n=t.split(".");let o=e;for(const e of n){if(Array.isArray(o)){const t=o.map((t=>this.resolveSegment(t,e))).flat().filter((e=>void 0!==e));o=t.length>0?t:void 0}else o=this.resolveSegment(o,e);if(void 0===o)return r}return Array.isArray(o)&&1===o.length?o[0]:void 0!==o?o:r}resolveSegment(e,t){if(null==e||"object"!=typeof e)return;if(t in e)return e[t];if(t===this.config.propNames.value||t===this.config.propNames.children||t===this.config.propNames.attributes||t===this.config.propNames.namespace||t===this.config.propNames.prefix||t===this.config.propNames.cdata||t===this.config.propNames.comments||t===this.config.propNames.instruction||t===this.config.propNames.target){const r=Object.entries(this.config.propNames).find((([e,r])=>r===t))?.[0];if(r&&void 0!==e[t])return e[t]}const r=e[this.config.propNames.children];if(Array.isArray(r)){const e=r.map((e=>t in e?e[t]:void 0)).filter((e=>void 0!==e));return e.length>0?e:void 0}}fromJSONObject(e,t){const r=this.wrapObject(e);if("string"==typeof t)return{[t]:r};if(t&&"object"==typeof t){const e=t.name||"root",n=t[this.config.propNames.prefix]||"",o=n?`${n}:${e}`:e,s={[o]:{}},i=this.config.propNames.attributes;t[i]&&Array.isArray(t[i])&&(s[o][i]=t[i]);const a=this.config.propNames.children,c=t[a]?t[a]:[];s[o][a]=[...c,{[e]:r}];const l=this.config.propNames.namespace;return t[l]&&(s[o][l]=t[l]),n&&t[l]&&(s[o][`xmlns:${n}`]=t[l]),s}return r}wrapObject(e){const t=this.config.propNames.value,r=this.config.propNames.children;if(null===e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e)return{[t]:e};if(Array.isArray(e))return{[r]:e.map((e=>this.wrapObject(e)))};if("object"==typeof e){const t=Object.entries(e).map((([e,t])=>({[e]:this.wrapObject(t)})));return{[r]:t}}}isEmpty(e){return null==e||(Array.isArray(e)?0===e.length:"object"==typeof e&&0===Object.keys(e).length)}safeStringify(e,t=2){try{return JSON.stringify(e,null,t)}catch(e){return"[Cannot stringify object]"}}deepClone(e){try{return JSON.parse(JSON.stringify(e))}catch(e){throw new Error(`Failed to deep clone object: ${e instanceof Error?e.message:String(e)}`)}}deepMerge(e,t){return t&&"object"==typeof t&&null!==t?e&&"object"==typeof e&&null!==e?(Object.keys(t).forEach((r=>{const n=t[r],o=e[r];null===n||null===o||"object"!=typeof n||"object"!=typeof o||Array.isArray(n)||Array.isArray(o)?e[r]=n:e[r]=this.deepMerge(o,n)})),e):t:e}}class o{constructor(e){this.config=e}applyTransforms(e,t){if(!this.config.valueTransforms||0===this.config.valueTransforms.length)return e;let r=e;for(const e of this.config.valueTransforms)r=e.process(r,t);return r}createContext(e,t,r,n={}){return{direction:e,nodeName:t,nodeType:r,path:n.path||t,namespace:n.namespace,prefix:n.prefix,isAttribute:n.isAttribute||!1,attributeName:n.attributeName,parent:n.parent,config:this.config}}getNodeTypeName(e){return r.getNodeTypeName(e)}}class s{constructor(e){this.config=e,this.jsonUtil=new n(this.config),this.transformUtil=new o(this.config)}parse(e){try{const n=r.parseFromString(e,"text/xml"),o=n.getElementsByTagName("parsererror");if(o.length>0)throw new t(`XML parsing error: ${o[0].textContent}`);return this.nodeToJson(n.documentElement)}catch(e){throw new t(`Failed to convert XML to JSON: ${e instanceof Error?e.message:String(e)}`)}}nodeToJson(e,t,n=""){const o={};if(e.nodeType===r.nodeTypes.ELEMENT_NODE){const s=e,i=s.localName||s.nodeName.split(":").pop()||s.nodeName,a=n?`${n}.${i}`:i,c={},l=this.transformUtil.createContext("xml-to-json",i,e.nodeType,{path:a,namespace:s.namespaceURI||void 0,prefix:s.prefix||void 0,parent:t});if(this.config.preserveNamespaces){const e=s.namespaceURI;e&&(c[this.config.propNames.namespace]=e);const t=s.prefix;t&&(c[this.config.propNames.prefix]=t)}if(this.config.preserveAttributes&&s.attributes.length>0){const t=[];for(let r=0;r0&&(c[this.config.propNames.attributes]=t)}if(s.childNodes.length>0){const e=[],t=this.config.propNames.children,n=this.config.propNames.value,o=this.config.propNames.cdata,i=this.config.propNames.comments,p=this.config.propNames.instruction,m=this.config.propNames.target;for(let t=0;t0&&(c[t]=e)}this.config.outputOptions.compact&&Object.keys(c).forEach((e=>{const t=this.cleanNode(c[e]);void 0===t?delete c[e]:c[e]=t})),o[i]=c}return o}cleanNode(e){if(Array.isArray(e)){const t=e.map((e=>this.cleanNode(e))).filter((e=>!(null==e||"object"==typeof e&&0===Object.keys(e).length)));return t.length>0?t:void 0}if("object"==typeof e&&null!==e){Object.keys(e).forEach((t=>{const r=this.cleanNode(e[t]);null==r||Array.isArray(r)&&0===r.length||"object"==typeof r&&0===Object.keys(r).length?delete e[t]:e[t]=r}));const t=this.config.propNames.children,r=this.config.propNames.attributes;if(Object.keys(e).every((e=>e===t||e===r))&&(void 0===e[t]||this.jsonUtil.isEmpty(e[t]))&&(void 0===e[r]||this.jsonUtil.isEmpty(e[r])))return;return Object.keys(e).length>0?e:void 0}return e}}class i{constructor(e){this.config=e}prettyPrintXml(e){const n=this.config.outputOptions.indent,o=" ".repeat(n);try{const t=r.parseFromString(e,"text/xml"),n=(e,t=0)=>{const s=o.repeat(t);switch(e.nodeType){case r.nodeTypes.ELEMENT_NODE:{const o=e,i=o.tagName,a=Array.from(o.attributes).map((e=>`${e.name}="${e.value}"`)).join(" "),c=a?`<${i} ${a}>`:`<${i}>`,l=Array.from(o.childNodes);if(0===l.length)return`${s}${c.replace(/>$/," />")}\n`;if(0===l.length||1===l.length&&l[0].nodeType===r.nodeTypes.TEXT_NODE&&""===l[0].textContent?.trim())return`${s}<${i}${a?" "+a:""}>\n`;return`${s}${c}\n${l.map((e=>n(e,t+1))).join("")}${s}\n`}case r.nodeTypes.TEXT_NODE:{const t=e.textContent?.trim();return t?`${s}${t}\n`:""}case r.nodeTypes.CDATA_SECTION_NODE:return`${s}\n`;case r.nodeTypes.COMMENT_NODE:return`${s}\x3c!--${e.nodeValue}--\x3e\n`;case r.nodeTypes.PROCESSING_INSTRUCTION_NODE:const o=e;return`${s}\n`;case r.nodeTypes.DOCUMENT_NODE:return Array.from(e.childNodes).map((e=>n(e,t))).join("");default:return""}};return n(t).trim()}catch(e){throw new t(`Failed to pretty print XML: ${e instanceof Error?e.message:String(e)}`)}}validateXML(e){try{const t=r.parseFromString(e,"text/xml").getElementsByTagName("parsererror");return t.length>0?{isValid:!1,message:t[0].textContent||"Unknown parsing error"}:{isValid:!0}}catch(e){return{isValid:!1,message:e instanceof Error?e.message:String(e)}}}ensureXMLDeclaration(e){return e.trim().startsWith("\n'+e}escapeXML(e){return"string"!=typeof e||0===e.length?"":e.replace(/[&<>"']/g,(e=>{switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";case"'":return"'";default:return e}}))}unescapeXML(e){return"string"!=typeof e||0===e.length?"":e.replace(/&(amp|lt|gt|quot|apos);/g,((e,t)=>{switch(t){case"amp":return"&";case"lt":return"<";case"gt":return">";case"quot":return'"';case"apos":return"'";default:return e}}))}extractPrefix(e){const t=e.indexOf(":");return t>0?e.substring(0,t):null}extractLocalName(e){const t=e.indexOf(":");return t>0?e.substring(t+1):e}createQualifiedName(e,t){return e?`${e}:${t}`:t}}class a{constructor(e){this.config=e,this.xmlUtil=new i(this.config),this.transformUtil=new o(this.config)}serialize(e){try{const t=r.createDocument(),n=this.jsonToNode(e,t);n&&(t.documentElement&&"temp"===t.documentElement.nodeName?t.replaceChild(n,t.documentElement):t.appendChild(n));let o=r.serializeToString(t);return o=o.replace(' xmlns="http://www.w3.org/1999/xhtml"',""),this.config.outputOptions.xml.declaration&&(o=this.xmlUtil.ensureXMLDeclaration(o)),this.config.outputOptions.prettyPrint&&(o=this.xmlUtil.prettyPrintXml(o)),o}catch(e){throw new t(`Failed to convert JSON to XML: ${e instanceof Error?e.message:String(e)}`)}}jsonToNode(e,t,n,o=""){if(!e||"object"!=typeof e)return null;const s=Object.keys(e)[0];if(!s)return null;const i=e[s],a=o?`${o}.${s}`:s;let c;const l=this.config.propNames.namespace,p=this.config.propNames.prefix,m=i[l],u=i[p],f=this.transformUtil.createContext("json-to-xml",s,r.nodeTypes.ELEMENT_NODE,{path:a,namespace:m,prefix:u,parent:n});c=m&&this.config.preserveNamespaces?u?r.createElementNS(m,`${u}:${s}`):r.createElementNS(m,s):r.createElement(s);const h=this.config.propNames.attributes,d=this.config.propNames.value;if(this.config.preserveAttributes&&i[h]&&Array.isArray(i[h])&&i[h].forEach((e=>{const t=Object.keys(e)[0];if(!t)return;const n=e[t],o=this.transformUtil.createContext("json-to-xml",s,r.nodeTypes.ELEMENT_NODE,{path:`${a}.${t}`,namespace:n[l],prefix:n[p],isAttribute:!0,attributeName:t,parent:f}),i=this.transformUtil.applyTransforms(n[d]||"",o),m=n[l],u=n[p];let h=t;u&&this.config.preserveNamespaces&&(h=`${u}:${t}`),r.setNamespacedAttribute(c,m&&this.config.preserveNamespaces?m:null,h,i)})),void 0!==i[d]){const e=this.transformUtil.createContext("json-to-xml",s,r.nodeTypes.TEXT_NODE,{path:`${a}.#text`,namespace:m,prefix:u,parent:f}),t=this.transformUtil.applyTransforms(i[d],e);c.textContent=t}const N=this.config.propNames.children,g=this.config.propNames.cdata,E=this.config.propNames.comments,T=this.config.propNames.instruction,y=this.config.propNames.target;return i[N]&&Array.isArray(i[N])&&i[N].forEach((e=>{if(void 0!==e[d]&&this.config.preserveTextNodes){const t=this.transformUtil.createContext("json-to-xml","#text",r.nodeTypes.TEXT_NODE,{path:`${a}.#text`,parent:f}),n=this.transformUtil.applyTransforms(e[d],t);c.appendChild(r.createTextNode(this.xmlUtil.escapeXML(n)))}else if(void 0!==e[g]&&this.config.preserveCDATA){const t=this.transformUtil.createContext("json-to-xml","#cdata",r.nodeTypes.CDATA_SECTION_NODE,{path:`${a}.#cdata`,parent:f}),n=this.transformUtil.applyTransforms(e[g],t);c.appendChild(r.createCDATASection(n))}else if(void 0!==e[E]&&this.config.preserveComments)c.appendChild(r.createComment(e[E]));else if(void 0!==e[T]&&this.config.preserveProcessingInstr){const t=e[T],n=t[y],o=t[d]||"";n&&c.appendChild(r.createProcessingInstruction(n,o))}else{const r=this.jsonToNode(e,t,f,a);r&&c.appendChild(r)}})),c}}const c={preserveNamespaces:!0,preserveComments:!0,preserveProcessingInstr:!0,preserveCDATA:!0,preserveTextNodes:!0,preserveWhitespace:!1,preserveAttributes:!0,outputOptions:{prettyPrint:!0,indent:2,compact:!0,json:{},xml:{declaration:!0}},propNames:{namespace:"$ns",prefix:"$pre",attributes:"$attr",value:"$val",cdata:"$cdata",comments:"$cmnt",instruction:"$pi",target:"$trgt",children:"$children"}};class l{constructor(e={}){this.jsonUtil=new n(c);const t=this.jsonUtil.deepClone(c);this.config=this.jsonUtil.deepMerge(t,e),this.jsonUtil=new n(this.config),this.xmlUtil=new i(this.config),this.xmltojson=new s(this.config),this.jsontoxml=new a(this.config)}xmlToJson(e){return this.xmltojson.parse(e)}jsonToXml(e){return this.jsontoxml.serialize(e)}prettyPrintXml(e){return this.xmlUtil.prettyPrintXml(e)}getPath(e,t,r=void 0){return this.jsonUtil.getPath(e,t,r)}validateXML(e){return this.xmlUtil.validateXML(e)}addTransformer(e){return this.config.valueTransforms||(this.config.valueTransforms=[]),this.config.valueTransforms.push(e),this}clearTransformers(){return this.config.valueTransforms=[],this}cleanup(){r.cleanup()}}return e.DEFAULT_CONFIG=c,e.ValueTransformer=class{process(e,t){return"xml-to-json"===t.direction?this.xmlToJson(e,t):this.jsonToXml(e,t)}xmlToJson(e,t){return e}jsonToXml(e,t){return e}},e.XJX=l,e.XJXError=t,e.default=l,Object.defineProperty(e,"__esModule",{value:!0}),e}({}); +//# sourceMappingURL=xjx.min.js.map diff --git a/dist/xjx.min.js.map b/dist/xjx.min.js.map new file mode 100644 index 0000000..7bb6595 --- /dev/null +++ b/dist/xjx.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"xjx.min.js","sources":["../../src/core/types/errors.ts","../../src/core/DOMAdapter.ts","../../src/core/utils/JsonUtils.ts","../../src/core/transforms/TransformUtil.ts","../../src/core/XmlToJsonConverter.ts","../../src/core/utils/XmlUtils.ts","../../src/core/JsonToXmlConverter.ts","../../src/core/config/config.ts","../../src/XJX.ts","../../src/core/transforms/ValueTransformer.ts"],"sourcesContent":["/**\n * Error classes for the XJX library\n */\n\n/**\n * Base error class\n */\nexport class XJXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'XMLToJSONError';\n }\n}\n\n/**\n * Error for XML parsing issues\n */\nexport class XMLParseError extends XJXError {\n constructor(message: string) {\n super(`XML parse error: ${message}`);\n this.name = 'XMLParseError';\n }\n}\n\n/**\n * Error for XML serialization issues\n */\nexport class XMLSerializeError extends XJXError {\n constructor(message: string) {\n super(`XML serialize error: ${message}`);\n this.name = 'XMLSerializeError';\n }\n}\n\n/**\n * Error for environment incompatibility\n */\nexport class EnvironmentError extends XJXError {\n constructor(message: string) {\n super(`Environment error: ${message}`);\n this.name = 'EnvironmentError';\n }\n}\n\n/**\n * Error for invalid configuration\n */\nexport class ConfigurationError extends XJXError {\n constructor(message: string) {\n super(`Configuration error: ${message}`);\n this.name = 'ConfigurationError';\n }\n}","/**\n * DOM Environment provider with unified interface for browser and Node.js\n */\nimport { XJXError } from './types/errors';\n\ninterface NodeTypes {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n}\n\ninterface DOMWindow {\n DOMParser: any;\n XMLSerializer: any;\n Node: {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n };\n document: Document;\n close?: () => void; \n}\n\ninterface JSDOMInstance {\n window: DOMWindow;\n}\n\nexport const DOMAdapter = (() => {\n // Environment-specific DOM implementation\n let domParser: any;\n let xmlSerializer: any;\n let nodeTypes: NodeTypes;\n let docImplementation: any;\n let jsdomInstance: JSDOMInstance | null = null;\n\n try {\n if (typeof window === \"undefined\") {\n // Node.js environment - try JSDOM first\n try {\n const { JSDOM } = require(\"jsdom\");\n jsdomInstance = new JSDOM(\"\", {\n contentType: \"text/xml\",\n }) as JSDOMInstance;\n\n domParser = jsdomInstance.window.DOMParser;\n xmlSerializer = jsdomInstance.window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE,\n TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE,\n CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE,\n COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line\n };\n docImplementation = jsdomInstance.window.document.implementation;\n } catch (jsdomError) {\n // Fall back to xmldom if JSDOM isn't available\n try {\n const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom');\n domParser = DOMParser;\n xmlSerializer = XMLSerializer;\n // Standard DOM node types\n nodeTypes = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n CDATA_SECTION_NODE: 4,\n COMMENT_NODE: 8,\n PROCESSING_INSTRUCTION_NODE: 7,\n DOCUMENT_NODE: 9, \n };\n const implementation = new DOMImplementation();\n docImplementation = implementation;\n } catch (xmldomError) {\n throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`);\n }\n }\n } else {\n // Browser environment\n if (!window.DOMParser) {\n throw new XJXError(\"DOMParser is not available in this environment\");\n }\n\n if (!window.XMLSerializer) {\n throw new XJXError(\"XMLSerializer is not available in this environment\");\n }\n\n domParser = window.DOMParser;\n xmlSerializer = window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: Node.ELEMENT_NODE,\n TEXT_NODE: Node.TEXT_NODE,\n CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE,\n COMMENT_NODE: Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: Node.DOCUMENT_NODE, \n };\n docImplementation = document.implementation;\n }\n } catch (error) {\n throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n return {\n createParser: () => {\n try {\n return new domParser();\n } catch (error) {\n throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createSerializer: () => {\n try {\n return new xmlSerializer();\n } catch (error) {\n throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n nodeTypes,\n \n parseFromString: (xmlString: string, contentType: string = 'text/xml') => {\n try {\n const parser = new domParser();\n return parser.parseFromString(xmlString, contentType);\n } catch (error) {\n throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n serializeToString: (node: Node) => {\n try {\n const serializer = new xmlSerializer();\n return serializer.serializeToString(node);\n } catch (error) {\n throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createDocument: () => {\n try {\n // For browsers, create a document with a root element to avoid issues\n if (typeof window !== \"undefined\") {\n const parser = new domParser();\n return parser.parseFromString('', 'text/xml');\n } else {\n return docImplementation.createDocument(null, null, null);\n }\n } catch (error) {\n throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElement: (tagName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElement(tagName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElement(tagName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElementNS: (namespaceURI: string, qualifiedName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElementNS(namespaceURI, qualifiedName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElementNS(namespaceURI, qualifiedName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createTextNode: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createTextNode(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createTextNode(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createCDATASection: (data: string) => {\n try {\n // For browser compatibility, use document.implementation to create CDATA\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createComment: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createComment(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createComment(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createProcessingInstruction: (target: string, data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n // New helper methods\n \n /**\n * Creates a proper namespace qualified attribute\n */\n setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => {\n try {\n if (namespaceURI) {\n element.setAttributeNS(namespaceURI, qualifiedName, value);\n } else {\n element.setAttribute(qualifiedName, value);\n }\n } catch (error) {\n throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n /**\n * Check if an object is a DOM node\n */\n isNode: (obj: any): boolean => {\n try {\n return obj && typeof obj === 'object' && typeof obj.nodeType === 'number';\n } catch (error) {\n return false;\n }\n },\n \n /**\n * Get DOM node type as string for debugging\n */\n getNodeTypeName: (nodeType: number): string => {\n switch (nodeType) {\n case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE';\n case nodeTypes.TEXT_NODE: return 'TEXT_NODE';\n case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE';\n case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE';\n case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE';\n default: return `UNKNOWN_NODE_TYPE(${nodeType})`;\n }\n },\n \n /**\n * Get all node attributes as an object\n */\n getNodeAttributes: (node: Element): Record => {\n const result: Record = {};\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n result[attr.name] = attr.value;\n }\n return result;\n },\n \n // Cleanup method (mainly for JSDOM)\n cleanup: () => {\n if (jsdomInstance && typeof jsdomInstance.window.close === 'function') {\n jsdomInstance.window.close();\n }\n }\n };\n})();","/**\n * JSONUtil - Utility functions for JSON processing\n */\nimport { Configuration } from \"../types/types\";\n\nexport class JSONUtil {\n private config: Configuration;\n\n /**\n * Constructor for JSONUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * Automatically traverses into children arrays and flattens results.\n *\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns Retrieved value or fallback\n */\n getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n const segments = path.split(\".\");\n let current: any = obj;\n\n for (const segment of segments) {\n if (Array.isArray(current)) {\n // Apply the segment to each array element and flatten results\n const results = current\n .map((item) => this.resolveSegment(item, segment))\n .flat()\n .filter((v) => v !== undefined);\n current = results.length > 0 ? results : undefined;\n } else {\n current = this.resolveSegment(current, segment);\n }\n\n if (current === undefined) return fallback;\n }\n\n // Collapse singleton arrays\n if (Array.isArray(current) && current.length === 1) {\n return current[0];\n }\n\n return current !== undefined ? current : fallback;\n }\n\n /**\n * Resolves a single path segment in the context of a JSON object.\n * Falls back to searching children for matching keys.\n *\n * @param obj The current object\n * @param segment The path segment to resolve\n * @returns Resolved value or undefined\n */\n private resolveSegment(obj: any, segment: string): any {\n if (obj == null || typeof obj !== \"object\") return undefined;\n\n // Direct property access\n if (segment in obj) {\n return obj[segment];\n }\n\n // Check if this is a special property name that matches the config\n if (\n segment === this.config.propNames.value ||\n segment === this.config.propNames.children ||\n segment === this.config.propNames.attributes ||\n segment === this.config.propNames.namespace ||\n segment === this.config.propNames.prefix ||\n segment === this.config.propNames.cdata ||\n segment === this.config.propNames.comments ||\n segment === this.config.propNames.instruction ||\n segment === this.config.propNames.target\n ) {\n const configKey = Object.entries(this.config.propNames).find(\n ([_, value]) => value === segment\n )?.[0];\n\n if (configKey && obj[segment] !== undefined) {\n return obj[segment];\n }\n }\n\n // Check children for objects that contain the segment\n const childrenKey = this.config.propNames.children;\n const children = obj[childrenKey];\n if (Array.isArray(children)) {\n const matches = children\n .map((child) => (segment in child ? child[segment] : undefined))\n .filter((v) => v !== undefined);\n return matches.length > 0 ? matches : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Converts a plain JSON object to the XML-like JSON structure.\n * Optionally wraps the result in a root element with attributes and namespaces.\n *\n * @param obj Standard JSON object\n * @param root Optional root element configuration (either a string or object with $ keys)\n * @returns XML-like JSON object\n */\n fromJSONObject(obj: any, root?: any): any {\n const wrappedObject = this.wrapObject(obj);\n\n if (typeof root === \"string\") {\n // Root is a simple string: wrap result with this root tag\n return { [root]: wrappedObject };\n }\n\n if (root && typeof root === \"object\") {\n // Handle root with config-based keys\n const elementName = root.name || \"root\"; // Default to \"root\" if no name is provided\n const prefix = root[this.config.propNames.prefix] || \"\";\n const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName;\n\n const result: any = {\n [qualifiedName]: {},\n };\n\n // Add attributes to the root element if defined\n const attrsKey = this.config.propNames.attributes;\n if (root[attrsKey] && Array.isArray(root[attrsKey])) {\n result[qualifiedName][attrsKey] = root[attrsKey];\n }\n\n // Merge existing children with the new generated children\n const childrenKey = this.config.propNames.children;\n const children = root[childrenKey] ? root[childrenKey] : [];\n result[qualifiedName][childrenKey] = [\n ...children,\n { [elementName]: wrappedObject },\n ];\n\n // Add namespace and prefix if defined\n const nsKey = this.config.propNames.namespace;\n if (root[nsKey]) {\n result[qualifiedName][nsKey] = root[nsKey];\n }\n\n if (prefix && root[nsKey]) {\n result[qualifiedName][`xmlns:${prefix}`] = root[nsKey];\n }\n\n return result;\n }\n\n // Default behavior if no root is provided\n return wrappedObject;\n }\n\n /**\n * Wraps a standard JSON value in the XML-like JSON structure\n * @param value Value to wrap\n * @returns Wrapped value\n */\n private wrapObject(value: any): any {\n const valKey = this.config.propNames.value;\n const childrenKey = this.config.propNames.children;\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return { [valKey]: value };\n }\n\n if (Array.isArray(value)) {\n // For arrays, wrap each item and return as a children-style array of repeated elements\n return {\n [childrenKey]: value.map((item) => {\n return this.wrapObject(item);\n }),\n };\n }\n\n if (typeof value === \"object\") {\n // It's an object: wrap its properties in children\n const children = Object.entries(value).map(([key, val]) => ({\n [key]: this.wrapObject(val),\n }));\n\n return { [childrenKey]: children };\n }\n\n return undefined; // Fallback for unhandled types\n }\n\n /**\n * Check if an object is empty\n * @param value Value to check\n * @returns true if empty\n */\n isEmpty(value: any): boolean {\n if (value == null) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n }\n\n /**\n * Safely stringify JSON for debugging\n * @param obj Object to stringify\n * @param indent Optional indentation level\n * @returns JSON string representation\n */\n safeStringify(obj: any, indent: number = 2): string {\n try {\n return JSON.stringify(obj, null, indent);\n } catch (error) {\n return \"[Cannot stringify object]\";\n }\n }\n\n /**\n * Deep clone an object\n * @param obj Object to clone\n * @returns Cloned object\n */\n deepClone(obj: any): any {\n try {\n return JSON.parse(JSON.stringify(obj));\n } catch (error) {\n throw new Error(\n `Failed to deep clone object: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Deep merge two objects with proper type handling\n * @param target Target object\n * @param source Source object\n * @returns Merged object (target is modified)\n */\n deepMerge(target: T, source: Partial): T {\n if (!source || typeof source !== \"object\" || source === null) {\n return target;\n }\n\n if (!target || typeof target !== \"object\" || target === null) {\n return source as unknown as T;\n }\n\n Object.keys(source).forEach((key) => {\n const sourceValue = source[key as keyof Partial];\n const targetValue = target[key as keyof T];\n\n // If both source and target values are objects, recursively merge them\n if (\n sourceValue !== null &&\n targetValue !== null &&\n typeof sourceValue === \"object\" &&\n typeof targetValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n !Array.isArray(targetValue)\n ) {\n // Recursively merge the nested objects\n (target as any)[key] = this.deepMerge(targetValue, sourceValue as any);\n } else {\n // Otherwise just replace the value\n (target as any)[key] = sourceValue;\n }\n });\n\n return target;\n }\n}\n","/**\n * Utilities for applying value transformations\n */\nimport { Configuration } from '../types/types';\nimport { TransformContext, TransformDirection } from './ValueTransformer';\nimport { DOMAdapter } from '../DOMAdapter';\n\n/**\n * Utility for applying value transformations\n */\nexport class TransformUtil {\n private config: Configuration;\n\n /**\n * Create a new TransformUtil\n * @param config Configuration\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Apply transforms to a value\n * @param value Value to transform\n * @param context Transformation context\n * @returns Transformed value\n */\n applyTransforms(value: any, context: TransformContext): any {\n // Skip transformation if no transformers are configured\n if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) {\n return value;\n }\n\n // Apply each transformer in sequence\n let transformedValue = value;\n for (const transformer of this.config.valueTransforms) {\n transformedValue = transformer.process(transformedValue, context);\n }\n\n return transformedValue;\n }\n\n /**\n * Create a transform context\n * @param direction Direction of transformation\n * @param nodeName Name of the current node\n * @param nodeType DOM node type\n * @param options Additional context options\n * @returns Transform context\n */\n createContext(\n direction: TransformDirection,\n nodeName: string,\n nodeType: number,\n options: {\n path?: string;\n namespace?: string;\n prefix?: string;\n isAttribute?: boolean;\n attributeName?: string;\n parent?: TransformContext;\n } = {}\n ): TransformContext {\n return {\n direction,\n nodeName,\n nodeType,\n path: options.path || nodeName,\n namespace: options.namespace,\n prefix: options.prefix,\n isAttribute: options.isAttribute || false,\n attributeName: options.attributeName,\n parent: options.parent,\n config: this.config,\n };\n }\n\n /**\n * Get a user-friendly node type name for debugging\n * @param nodeType DOM node type\n * @returns String representation of node type\n */\n getNodeTypeName(nodeType: number): string {\n return DOMAdapter.getNodeTypeName(nodeType);\n }\n}","/**\n * XMLToJSON class for converting XML to JSON with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { JSONUtil } from \"./utils/JsonUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * XMLToJSON Parser for converting XML to JSON\n */\nexport class XMLToJSON {\n private config: Configuration;\n private jsonUtil: JSONUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for XMLToJSON\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.jsonUtil = new JSONUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public parse(xmlString: string): Record {\n try {\n const xmlDoc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n // Check for parsing errors\n const errors = xmlDoc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n throw new XJXError(`XML parsing error: ${errors[0].textContent}`);\n }\n\n return this.nodeToJson(xmlDoc.documentElement);\n } catch (error) {\n throw new XJXError(\n `Failed to convert XML to JSON: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert a DOM node to JSON representation\n * @param node DOM node to convert\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the XML tree\n * @returns JSON representation of the node\n */\n private nodeToJson(node: Node, parentContext?: TransformContext, path: string = \"\"): Record {\n const result: Record = {};\n\n // Handle element nodes\n if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n const element = node as Element;\n // Use localName instead of nodeName to strip namespace prefix\n const nodeName =\n element.localName ||\n element.nodeName.split(\":\").pop() ||\n element.nodeName;\n\n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n const nodeObj: Record = {};\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: currentPath,\n namespace: element.namespaceURI || undefined,\n prefix: element.prefix || undefined,\n parent: parentContext\n }\n );\n\n // Process namespaces if enabled\n if (this.config.preserveNamespaces) {\n const ns = element.namespaceURI;\n if (ns) {\n nodeObj[this.config.propNames.namespace] = ns;\n }\n\n const prefix = element.prefix;\n if (prefix) {\n nodeObj[this.config.propNames.prefix] = prefix;\n }\n }\n\n // Process attributes if enabled\n if (this.config.preserveAttributes && element.attributes.length > 0) {\n const attrs: Array> = [];\n\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n // Strip namespace prefix from attribute name\n const attrLocalName =\n attr.localName || attr.name.split(\":\").pop() || attr.name;\n\n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: `${currentPath}.${attrLocalName}`,\n namespace: attr.namespaceURI || undefined,\n prefix: attr.prefix || undefined,\n isAttribute: true,\n attributeName: attrLocalName,\n parent: context\n }\n );\n\n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attr.value,\n attrContext\n );\n\n // Create attribute object with consistent structure\n const attrObj: Record = {\n [attrLocalName]: {\n [this.config.propNames.value]: transformedValue,\n },\n };\n\n // Add namespace info for attribute if present and enabled\n if (this.config.preserveNamespaces) {\n // Handle attribute namespace\n if (attr.namespaceURI) {\n attrObj[attrLocalName][this.config.propNames.namespace] =\n attr.namespaceURI;\n }\n\n // Handle attribute prefix\n if (attr.prefix) {\n attrObj[attrLocalName][this.config.propNames.prefix] =\n attr.prefix;\n }\n }\n\n attrs.push(attrObj);\n }\n\n if (attrs.length > 0) {\n nodeObj[this.config.propNames.attributes] = attrs;\n }\n }\n\n // Process child nodes\n if (element.childNodes.length > 0) {\n const children: Array> = [];\n const childrenKey = this.config.propNames.children;\n const valueKey = this.config.propNames.value;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n\n // Text nodes - only process if preserveTextNodes is true\n if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) {\n if (this.config.preserveTextNodes) {\n let text = child.nodeValue || \"\";\n\n // Skip whitespace-only text nodes if whitespace preservation is disabled\n if (!this.config.preserveWhitespace) {\n if (text.trim() === \"\") {\n continue;\n }\n // Trim the text when preserveWhitespace is false\n text = text.trim();\n }\n\n // Create text node context\n const textContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#text',\n child.nodeType,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n\n // Apply transformations to text value\n const transformedText = this.transformUtil.applyTransforms(\n text,\n textContext\n );\n\n children.push({ [valueKey]: transformedText });\n }\n }\n // CDATA sections\n else if (\n child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE &&\n this.config.preserveCDATA\n ) {\n // Create CDATA context\n const cdataContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#cdata',\n child.nodeType,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n\n // Apply transformations to CDATA value\n const transformedCData = this.transformUtil.applyTransforms(\n child.nodeValue || \"\",\n cdataContext\n );\n\n children.push({\n [cdataKey]: transformedCData,\n });\n }\n // Comments\n else if (\n child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE &&\n this.config.preserveComments\n ) {\n children.push({\n [commentsKey]: child.nodeValue || \"\",\n });\n }\n // Processing instructions\n else if (\n child.nodeType ===\n DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE &&\n this.config.preserveProcessingInstr\n ) {\n children.push({\n [instructionKey]: {\n [targetKey]: child.nodeName,\n [valueKey]: child.nodeValue || \"\",\n },\n });\n }\n // Element nodes (recursive)\n else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n children.push(this.nodeToJson(child, context, currentPath));\n }\n }\n\n if (children.length > 0) {\n nodeObj[childrenKey] = children;\n }\n }\n\n // Apply compact option - remove empty properties if enabled\n if (this.config.outputOptions.compact) {\n Object.keys(nodeObj).forEach((key) => {\n const cleaned = this.cleanNode(nodeObj[key]);\n if (cleaned === undefined) {\n delete nodeObj[key];\n } else {\n nodeObj[key] = cleaned;\n }\n });\n }\n\n result[nodeName] = nodeObj;\n }\n\n return result;\n }\n\n private cleanNode(node: any): any {\n if (Array.isArray(node)) {\n // Clean each item in the array and filter out empty ones\n const cleanedArray = node\n .map((item) => this.cleanNode(item))\n .filter((item) => {\n return !(\n item === null ||\n item === undefined ||\n (typeof item === \"object\" && Object.keys(item).length === 0)\n );\n });\n return cleanedArray.length > 0 ? cleanedArray : undefined;\n } else if (typeof node === \"object\" && node !== null) {\n // Clean properties recursively\n Object.keys(node).forEach((key) => {\n const cleanedChild = this.cleanNode(node[key]);\n if (\n cleanedChild === null ||\n cleanedChild === undefined ||\n (Array.isArray(cleanedChild) && cleanedChild.length === 0) ||\n (typeof cleanedChild === \"object\" &&\n Object.keys(cleanedChild).length === 0)\n ) {\n delete node[key];\n } else {\n node[key] = cleanedChild;\n }\n });\n\n // Handle the special case for nodes with only empty children/attributes\n const childrenKey = this.config.propNames.children;\n const attrsKey = this.config.propNames.attributes;\n const keys = Object.keys(node);\n if (\n keys.every((key) => key === childrenKey || key === attrsKey) &&\n (node[childrenKey] === undefined ||\n this.jsonUtil.isEmpty(node[childrenKey])) &&\n (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))\n ) {\n return undefined;\n }\n\n return Object.keys(node).length > 0 ? node : undefined;\n }\n\n return node;\n }\n}","/**\n * XMLUtil - Utility functions for XML processing\n */\nimport { XJXError } from \"../types/errors\";\nimport { DOMAdapter } from \"../DOMAdapter\";\nimport { Configuration } from \"../types/types\";\n\nexport class XMLUtil {\n private config: Configuration;\n\n /**\n * Constructor for XMLUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n prettyPrintXml(xmlString: string): string {\n const indent = this.config.outputOptions.indent;\n const INDENT = \" \".repeat(indent);\n\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n const serializer = (node: Node, level = 0): string => {\n const pad = INDENT.repeat(level);\n\n switch (node.nodeType) {\n case DOMAdapter.nodeTypes.ELEMENT_NODE: {\n const el = node as Element;\n const tagName = el.tagName;\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`;\n\n const children = Array.from(el.childNodes);\n\n if (children.length === 0) {\n return `${pad}${openTag.replace(/>$/, \" />\")}\\n`;\n }\n\n // Single text node: print inline\n if (\n children.length === 0 ||\n (children.length === 1 &&\n children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE &&\n children[0].textContent?.trim() === \"\")\n ) {\n // Empty or whitespace-only\n return `${pad}<${tagName}${attrs ? \" \" + attrs : \"\"}>\\n`;\n }\n\n const inner = children\n .map((child) => serializer(child, level + 1))\n .join(\"\");\n return `${pad}${openTag}\\n${inner}${pad}\\n`;\n }\n\n case DOMAdapter.nodeTypes.TEXT_NODE: {\n const text = node.textContent?.trim();\n return text ? `${pad}${text}\\n` : \"\";\n }\n\n case DOMAdapter.nodeTypes.CDATA_SECTION_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.COMMENT_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE:\n const pi = node as ProcessingInstruction;\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.DOCUMENT_NODE:\n return Array.from(node.childNodes)\n .map((child) => serializer(child, level))\n .join(\"\");\n\n default:\n return \"\";\n }\n };\n\n return serializer(doc).trim();\n } catch (error) {\n throw new XJXError(\n `Failed to pretty print XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Check if XML string is well-formed\n * @param xmlString XML string to validate\n * @returns Object with validation result and any error messages\n */\n validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n const errors = doc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n return {\n isValid: false,\n message: errors[0].textContent || \"Unknown parsing error\",\n };\n }\n return { isValid: true };\n } catch (error) {\n return {\n isValid: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Add XML declaration to a string if missing\n * @param xmlString XML string\n * @returns XML string with declaration\n */\n ensureXMLDeclaration(xmlString: string): string {\n if (!xmlString.trim().startsWith(\"\\n' + xmlString;\n }\n return xmlString;\n }\n\n /**\n * Escapes special characters in text for safe XML usage.\n * @param text Text to escape.\n * @returns Escaped XML string.\n */\n escapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&\";\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case '\"':\n return \""\";\n case \"'\":\n return \"'\";\n default:\n return char;\n }\n });\n }\n\n /**\n * Unescapes XML entities back to their character equivalents.\n * @param text Text with XML entities.\n * @returns Unescaped text.\n */\n unescapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => {\n switch (entity) {\n case \"amp\":\n return \"&\";\n case \"lt\":\n return \"<\";\n case \"gt\":\n return \">\";\n case \"quot\":\n return '\"';\n case \"apos\":\n return \"'\";\n default:\n return match;\n }\n });\n }\n\n /**\n * Extract the namespace prefix from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Prefix or null if no prefix\n */\n extractPrefix(qualifiedName: string): string | null {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null;\n }\n\n /**\n * Extract the local name from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Local name\n */\n extractLocalName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0\n ? qualifiedName.substring(colonIndex + 1)\n : qualifiedName;\n }\n\n /**\n * Create a qualified name from prefix and local name\n * @param prefix Namespace prefix (can be null)\n * @param localName Local name\n * @returns Qualified name\n */\n createQualifiedName(prefix: string | null, localName: string): string {\n return prefix ? `${prefix}:${localName}` : localName;\n }\n}","/**\n * JSONToXML class for converting JSON to XML with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { XMLUtil } from \"./utils/XmlUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * JSONToXML for converting JSON to XML\n */\nexport class JSONToXML {\n private config: Configuration;\n private xmlUtil: XMLUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for JSONToXML\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.xmlUtil = new XMLUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert JSON object to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public serialize(jsonObj: Record): string {\n try {\n const doc = DOMAdapter.createDocument();\n const rootElement = this.jsonToNode(jsonObj, doc);\n\n if (rootElement) {\n // Handle the temporary root element if it exists\n if (doc.documentElement && doc.documentElement.nodeName === \"temp\") {\n doc.replaceChild(rootElement, doc.documentElement);\n } else {\n doc.appendChild(rootElement);\n }\n }\n\n // Add XML declaration if specified\n let xmlString = DOMAdapter.serializeToString(doc);\n\n // remove xhtml decl inserted by dom\n xmlString = xmlString.replace(' xmlns=\"http://www.w3.org/1999/xhtml\"', '');\n\n if (this.config.outputOptions.xml.declaration) {\n xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString);\n }\n\n // Apply pretty printing if enabled\n if (this.config.outputOptions.prettyPrint) {\n xmlString = this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n return xmlString;\n } catch (error) {\n throw new XJXError(\n `Failed to convert JSON to XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert JSON object to DOM node\n * @param jsonObj JSON object to convert\n * @param doc Document for creating elements\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the JSON object\n * @returns DOM Element\n */\n private jsonToNode(\n jsonObj: Record,\n doc: Document,\n parentContext?: TransformContext,\n path: string = \"\"\n ): Element | null {\n if (!jsonObj || typeof jsonObj !== \"object\") {\n return null;\n }\n\n // Get the node name (first key in the object)\n const nodeName = Object.keys(jsonObj)[0];\n if (!nodeName) {\n return null;\n }\n\n const nodeData = jsonObj[nodeName];\n \n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n // Create element with namespace if available\n let element: Element;\n const namespaceKey = this.config.propNames.namespace;\n const prefixKey = this.config.propNames.prefix;\n const ns = nodeData[namespaceKey];\n const prefix = nodeData[prefixKey];\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: currentPath,\n namespace: ns,\n prefix: prefix,\n parent: parentContext\n }\n );\n\n if (ns && this.config.preserveNamespaces) {\n if (prefix) {\n // Create element with namespace and prefix\n element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`);\n } else {\n // Create element with namespace but no prefix\n element = DOMAdapter.createElementNS(ns, nodeName);\n }\n } else {\n // Create element without namespace\n element = DOMAdapter.createElement(nodeName);\n }\n\n // Process attributes if enabled\n const attributesKey = this.config.propNames.attributes;\n const valueKey = this.config.propNames.value;\n if (\n this.config.preserveAttributes &&\n nodeData[attributesKey] &&\n Array.isArray(nodeData[attributesKey])\n ) {\n nodeData[attributesKey].forEach(\n (attrObj: Record) => {\n const attrName = Object.keys(attrObj)[0];\n if (!attrName) return;\n\n const attrData = attrObj[attrName];\n \n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: `${currentPath}.${attrName}`,\n namespace: attrData[namespaceKey],\n prefix: attrData[prefixKey],\n isAttribute: true,\n attributeName: attrName,\n parent: context\n }\n );\n \n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attrData[valueKey] || \"\",\n attrContext\n );\n \n const attrNs = attrData[namespaceKey];\n const attrPrefix = attrData[prefixKey];\n\n // Form qualified name for attribute if it has a prefix\n let qualifiedName = attrName;\n if (attrPrefix && this.config.preserveNamespaces) {\n qualifiedName = `${attrPrefix}:${attrName}`;\n }\n\n DOMAdapter.setNamespacedAttribute(\n element, \n (attrNs && this.config.preserveNamespaces) ? attrNs : null, \n qualifiedName, \n transformedValue\n );\n }\n );\n }\n\n // Process simple text value\n if (nodeData[valueKey] !== undefined) {\n // Apply transformations to text value\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n namespace: ns,\n prefix: prefix,\n parent: context\n }\n );\n \n const transformedValue = this.transformUtil.applyTransforms(\n nodeData[valueKey],\n textContext\n );\n \n element.textContent = transformedValue;\n }\n\n // Process children\n const childrenKey = this.config.propNames.children;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n if (\n nodeData[childrenKey] &&\n Array.isArray(nodeData[childrenKey])\n ) {\n nodeData[childrenKey].forEach(\n (child: Record) => {\n // Text nodes\n if (\n child[valueKey] !== undefined &&\n this.config.preserveTextNodes\n ) {\n // Apply transformations to text node\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#text',\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n \n const transformedText = this.transformUtil.applyTransforms(\n child[valueKey],\n textContext\n );\n \n element.appendChild(\n DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))\n );\n }\n // CDATA sections\n else if (\n child[cdataKey] !== undefined &&\n this.config.preserveCDATA\n ) {\n // Apply transformations to CDATA\n const cdataContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#cdata',\n DOMAdapter.nodeTypes.CDATA_SECTION_NODE,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n \n const transformedCData = this.transformUtil.applyTransforms(\n child[cdataKey],\n cdataContext\n );\n \n element.appendChild(\n DOMAdapter.createCDATASection(\n transformedCData\n )\n );\n }\n // Comments\n else if (\n child[commentsKey] !== undefined &&\n this.config.preserveComments\n ) {\n element.appendChild(\n DOMAdapter.createComment(\n child[commentsKey]\n )\n );\n }\n // Processing instructions\n else if (\n child[instructionKey] !== undefined &&\n this.config.preserveProcessingInstr\n ) {\n const piData = child[instructionKey];\n const target = piData[targetKey];\n const data = piData[valueKey] || \"\";\n\n if (target) {\n element.appendChild(\n DOMAdapter.createProcessingInstruction(target, data)\n );\n }\n }\n // Element nodes (recursive)\n else {\n const childElement = this.jsonToNode(child, doc, context, currentPath);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n }\n );\n }\n\n return element;\n }\n}","/**\n * Default configuration for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: Configuration = {\n preserveNamespaces: true,\n preserveComments: true,\n preserveProcessingInstr: true,\n preserveCDATA: true,\n preserveTextNodes: true,\n preserveWhitespace: false,\n preserveAttributes: true,\n\n outputOptions: {\n prettyPrint: true,\n indent: 2,\n compact: true,\n json: {},\n xml: {\n declaration: true,\n },\n },\n\n propNames: {\n namespace: \"$ns\",\n prefix: \"$pre\",\n attributes: \"$attr\",\n value: \"$val\",\n cdata: \"$cdata\",\n comments: \"$cmnt\",\n instruction: \"$pi\", \n target: \"$trgt\", \n children: \"$children\",\n },\n};","/**\n * XJX - Facade class for XML-JSON conversion operations\n */\nimport { XMLToJSON } from \"./core/XmlToJsonConverter\";\nimport { JSONToXML } from \"./core/JsonToXmlConverter\";\nimport { Configuration } from \"./core/types/types\";\nimport { DEFAULT_CONFIG } from \"./core/config/config\";\nimport { DOMAdapter } from \"./core/DOMAdapter\";\nimport { XMLUtil } from \"./core/utils/XmlUtils\";\nimport { JSONUtil } from \"./core/utils/JsonUtils\";\nimport { ValueTransformer } from \"./core/transforms\";\n\nexport class XJX {\n private config: Configuration;\n private xmltojson: XMLToJSON;\n private jsontoxml: JSONToXML;\n private jsonUtil: JSONUtil;\n private xmlUtil: XMLUtil;\n\n /**\n * Constructor for XJX utility\n * @param config Configuration options\n */\n constructor(config: Partial = {}) {\n // First create a jsonUtil instance with default config to use its methods\n this.jsonUtil = new JSONUtil(DEFAULT_CONFIG);\n\n // Create a deep clone of the default config\n const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG);\n\n // Deep merge with the provided config\n this.config = this.jsonUtil.deepMerge(defaultClone, config);\n\n // Re-initialize jsonUtil with the merged config\n this.jsonUtil = new JSONUtil(this.config);\n\n // Initialize other components\n this.xmlUtil = new XMLUtil(this.config);\n this.xmltojson = new XMLToJSON(this.config);\n this.jsontoxml = new JSONToXML(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public xmlToJson(xmlString: string): Record {\n return this.xmltojson.parse(xmlString);\n }\n\n /**\n * Convert JSON object back to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public jsonToXml(jsonObj: Record): string {\n return this.jsontoxml.serialize(jsonObj);\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n public prettyPrintXml(xmlString: string): string {\n return this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns The value at the specified path or the fallback value\n */\n public getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n return this.jsonUtil.getPath(obj, path, fallback);\n }\n\n /**\n * Validate XML string\n * @param xmlString XML string to validate\n * @returns Validation result\n */\n public validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n return this.xmlUtil.validateXML(xmlString);\n }\n\n /**\n * Add a value transformer to the configuration\n * @param transformer Value transformer to add\n * @returns This XJX instance for chaining\n */\n public addTransformer(transformer: ValueTransformer): XJX {\n if (!this.config.valueTransforms) {\n this.config.valueTransforms = [];\n }\n this.config.valueTransforms.push(transformer);\n return this;\n }\n\n /**\n * Removes all value transformers from the configuration\n * @returns This XJX instance for chaining\n */\n public clearTransformers(): XJX {\n this.config.valueTransforms = [];\n return this;\n }\n\n /**\n * Clean up any resources\n */\n public cleanup(): void {\n DOMAdapter.cleanup();\n }\n}","/**\n * Value transformation types and base class for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Direction of the transformation\n */\nexport type TransformDirection = 'xml-to-json' | 'json-to-xml';\n\n/**\n * Context provided to value transformers\n */\nexport interface TransformContext {\n // Core transformation info\n direction: TransformDirection; // Direction of the current transformation\n \n // Node information\n nodeName: string; // Name of the current node\n nodeType: number; // DOM node type (element, text, etc.)\n namespace?: string; // Namespace URI if available\n prefix?: string; // Namespace prefix if available\n \n // Structure information\n path: string; // Dot-notation path to current node\n isAttribute: boolean; // Whether the current value is from an attribute\n attributeName?: string; // Name of attribute if isAttribute is true\n \n // Parent context (creates a chain)\n parent?: TransformContext; // Reference to parent context for traversal\n \n // Configuration reference\n config: Configuration; // Reference to the current configuration\n}\n\n/**\n * Abstract base class for value transformers\n */\nexport abstract class ValueTransformer {\n /**\n * Process a value, transforming it if applicable\n * @param value Value to potentially transform\n * @param context Context including direction and other information\n * @returns Transformed value or original if not applicable\n */\n process(value: any, context: TransformContext): any {\n if (context.direction === 'xml-to-json') {\n return this.xmlToJson(value, context);\n } else {\n return this.jsonToXml(value, context);\n }\n }\n\n /**\n * Transform a value from XML to JSON representation\n * @param value Value from XML\n * @param context Transformation context\n * @returns Transformed value for JSON\n */\n protected xmlToJson(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n\n /**\n * Transform a value from JSON to XML representation\n * @param value Value from JSON\n * @param context Transformation context\n * @returns Transformed value for XML\n */\n protected jsonToXml(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n}"],"names":["XJXError","Error","constructor","message","super","this","name","DOMAdapter","domParser","xmlSerializer","nodeTypes","docImplementation","jsdomInstance","window","JSDOM","require","contentType","DOMParser","XMLSerializer","ELEMENT_NODE","Node","TEXT_NODE","CDATA_SECTION_NODE","COMMENT_NODE","PROCESSING_INSTRUCTION_NODE","DOCUMENT_NODE","document","implementation","jsdomError","DOMImplementation","xmldomError","error","String","createParser","createSerializer","parseFromString","xmlString","serializeToString","node","createDocument","createElement","tagName","createElementNS","namespaceURI","qualifiedName","createTextNode","data","createCDATASection","createComment","createProcessingInstruction","target","setNamespacedAttribute","element","value","setAttributeNS","setAttribute","isNode","obj","nodeType","getNodeTypeName","getNodeAttributes","result","i","attributes","length","attr","cleanup","close","JSONUtil","config","getPath","path","fallback","undefined","segments","split","current","segment","Array","isArray","results","map","item","resolveSegment","flat","filter","v","propNames","children","namespace","prefix","cdata","comments","instruction","configKey","Object","entries","find","_","matches","child","fromJSONObject","root","wrappedObject","wrapObject","elementName","attrsKey","childrenKey","nsKey","valKey","key","val","isEmpty","keys","safeStringify","indent","JSON","stringify","deepClone","parse","deepMerge","source","forEach","sourceValue","targetValue","TransformUtil","applyTransforms","context","valueTransforms","transformedValue","transformer","process","createContext","direction","nodeName","options","isAttribute","attributeName","parent","XMLToJSON","jsonUtil","transformUtil","xmlDoc","errors","getElementsByTagName","textContent","nodeToJson","documentElement","parentContext","localName","pop","currentPath","nodeObj","preserveNamespaces","ns","preserveAttributes","attrs","attrLocalName","attrContext","attrObj","push","childNodes","valueKey","cdataKey","commentsKey","instructionKey","targetKey","preserveTextNodes","text","nodeValue","preserveWhitespace","trim","textContext","transformedText","preserveCDATA","cdataContext","transformedCData","preserveComments","preserveProcessingInstr","outputOptions","compact","cleaned","cleanNode","cleanedArray","cleanedChild","every","XMLUtil","prettyPrintXml","INDENT","repeat","doc","serializer","level","pad","el","from","a","join","openTag","replace","pi","validateXML","isValid","ensureXMLDeclaration","startsWith","escapeXML","char","unescapeXML","match","entity","extractPrefix","colonIndex","indexOf","substring","extractLocalName","createQualifiedName","JSONToXML","xmlUtil","serialize","jsonObj","rootElement","jsonToNode","replaceChild","appendChild","xml","declaration","prettyPrint","nodeData","namespaceKey","prefixKey","attributesKey","attrName","attrData","attrNs","attrPrefix","piData","childElement","DEFAULT_CONFIG","json","XJX","defaultClone","xmltojson","jsontoxml","xmlToJson","jsonToXml","addTransformer","clearTransformers"],"mappings":"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"} \ No newline at end of file diff --git a/dist/xjx.umd.js b/dist/xjx.umd.js new file mode 100644 index 0000000..aead58e --- /dev/null +++ b/dist/xjx.umd.js @@ -0,0 +1,1403 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.XJX = {})); +})(this, (function (exports) { 'use strict'; + + /** + * Error classes for the XJX library + */ + /** + * Base error class + */ + class XJXError extends Error { + constructor(message) { + super(message); + this.name = 'XMLToJSONError'; + } + } + + /** + * DOM Environment provider with unified interface for browser and Node.js + */ + const DOMAdapter = (() => { + // Environment-specific DOM implementation + let domParser; + let xmlSerializer; + let nodeTypes; + let docImplementation; + let jsdomInstance = null; + try { + if (typeof window === "undefined") { + // Node.js environment - try JSDOM first + try { + const { JSDOM } = require("jsdom"); + jsdomInstance = new JSDOM("", { + contentType: "text/xml", + }); + domParser = jsdomInstance.window.DOMParser; + xmlSerializer = jsdomInstance.window.XMLSerializer; + nodeTypes = { + ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE, + TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE, + CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE, + COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE, + PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE, + DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line + }; + docImplementation = jsdomInstance.window.document.implementation; + } + catch (jsdomError) { + // Fall back to xmldom if JSDOM isn't available + try { + const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom'); + domParser = DOMParser; + xmlSerializer = XMLSerializer; + // Standard DOM node types + nodeTypes = { + ELEMENT_NODE: 1, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + COMMENT_NODE: 8, + PROCESSING_INSTRUCTION_NODE: 7, + DOCUMENT_NODE: 9, + }; + const implementation = new DOMImplementation(); + docImplementation = implementation; + } + catch (xmldomError) { + throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`); + } + } + } + else { + // Browser environment + if (!window.DOMParser) { + throw new XJXError("DOMParser is not available in this environment"); + } + if (!window.XMLSerializer) { + throw new XJXError("XMLSerializer is not available in this environment"); + } + domParser = window.DOMParser; + xmlSerializer = window.XMLSerializer; + nodeTypes = { + ELEMENT_NODE: Node.ELEMENT_NODE, + TEXT_NODE: Node.TEXT_NODE, + CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE, + COMMENT_NODE: Node.COMMENT_NODE, + PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE, + DOCUMENT_NODE: Node.DOCUMENT_NODE, + }; + docImplementation = document.implementation; + } + } + catch (error) { + throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`); + } + return { + createParser: () => { + try { + return new domParser(); + } + catch (error) { + throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createSerializer: () => { + try { + return new xmlSerializer(); + } + catch (error) { + throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`); + } + }, + nodeTypes, + parseFromString: (xmlString, contentType = 'text/xml') => { + try { + const parser = new domParser(); + return parser.parseFromString(xmlString, contentType); + } + catch (error) { + throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`); + } + }, + serializeToString: (node) => { + try { + const serializer = new xmlSerializer(); + return serializer.serializeToString(node); + } + catch (error) { + throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createDocument: () => { + try { + // For browsers, create a document with a root element to avoid issues + if (typeof window !== "undefined") { + const parser = new domParser(); + return parser.parseFromString('', 'text/xml'); + } + else { + return docImplementation.createDocument(null, null, null); + } + } + catch (error) { + throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createElement: (tagName) => { + try { + if (typeof window !== "undefined") { + return document.createElement(tagName); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createElement(tagName); + } + } + catch (error) { + throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createElementNS: (namespaceURI, qualifiedName) => { + try { + if (typeof window !== "undefined") { + return document.createElementNS(namespaceURI, qualifiedName); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createElementNS(namespaceURI, qualifiedName); + } + } + catch (error) { + throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createTextNode: (data) => { + try { + if (typeof window !== "undefined") { + return document.createTextNode(data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createTextNode(data); + } + } + catch (error) { + throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createCDATASection: (data) => { + try { + // For browser compatibility, use document.implementation to create CDATA + if (typeof window !== "undefined") { + const doc = document.implementation.createDocument(null, null, null); + return doc.createCDATASection(data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createCDATASection(data); + } + } + catch (error) { + throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createComment: (data) => { + try { + if (typeof window !== "undefined") { + return document.createComment(data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createComment(data); + } + } + catch (error) { + throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`); + } + }, + createProcessingInstruction: (target, data) => { + try { + if (typeof window !== "undefined") { + const doc = document.implementation.createDocument(null, null, null); + return doc.createProcessingInstruction(target, data); + } + else { + const doc = docImplementation.createDocument(null, null, null); + return doc.createProcessingInstruction(target, data); + } + } + catch (error) { + throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`); + } + }, + // New helper methods + /** + * Creates a proper namespace qualified attribute + */ + setNamespacedAttribute: (element, namespaceURI, qualifiedName, value) => { + try { + if (namespaceURI) { + element.setAttributeNS(namespaceURI, qualifiedName, value); + } + else { + element.setAttribute(qualifiedName, value); + } + } + catch (error) { + throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`); + } + }, + /** + * Check if an object is a DOM node + */ + isNode: (obj) => { + try { + return obj && typeof obj === 'object' && typeof obj.nodeType === 'number'; + } + catch (error) { + return false; + } + }, + /** + * Get DOM node type as string for debugging + */ + getNodeTypeName: (nodeType) => { + switch (nodeType) { + case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE'; + case nodeTypes.TEXT_NODE: return 'TEXT_NODE'; + case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE'; + case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE'; + case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE'; + default: return `UNKNOWN_NODE_TYPE(${nodeType})`; + } + }, + /** + * Get all node attributes as an object + */ + getNodeAttributes: (node) => { + const result = {}; + for (let i = 0; i < node.attributes.length; i++) { + const attr = node.attributes[i]; + result[attr.name] = attr.value; + } + return result; + }, + // Cleanup method (mainly for JSDOM) + cleanup: () => { + if (jsdomInstance && typeof jsdomInstance.window.close === 'function') { + jsdomInstance.window.close(); + } + } + }; + })(); + + class JSONUtil { + /** + * Constructor for JSONUtil + * @param config Configuration options + */ + constructor(config) { + this.config = config; + } + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * Automatically traverses into children arrays and flattens results. + * + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns Retrieved value or fallback + */ + getPath(obj, path, fallback = undefined) { + const segments = path.split("."); + let current = obj; + for (const segment of segments) { + if (Array.isArray(current)) { + // Apply the segment to each array element and flatten results + const results = current + .map((item) => this.resolveSegment(item, segment)) + .flat() + .filter((v) => v !== undefined); + current = results.length > 0 ? results : undefined; + } + else { + current = this.resolveSegment(current, segment); + } + if (current === undefined) + return fallback; + } + // Collapse singleton arrays + if (Array.isArray(current) && current.length === 1) { + return current[0]; + } + return current !== undefined ? current : fallback; + } + /** + * Resolves a single path segment in the context of a JSON object. + * Falls back to searching children for matching keys. + * + * @param obj The current object + * @param segment The path segment to resolve + * @returns Resolved value or undefined + */ + resolveSegment(obj, segment) { + if (obj == null || typeof obj !== "object") + return undefined; + // Direct property access + if (segment in obj) { + return obj[segment]; + } + // Check if this is a special property name that matches the config + if (segment === this.config.propNames.value || + segment === this.config.propNames.children || + segment === this.config.propNames.attributes || + segment === this.config.propNames.namespace || + segment === this.config.propNames.prefix || + segment === this.config.propNames.cdata || + segment === this.config.propNames.comments || + segment === this.config.propNames.instruction || + segment === this.config.propNames.target) { + const configKey = Object.entries(this.config.propNames).find(([_, value]) => value === segment)?.[0]; + if (configKey && obj[segment] !== undefined) { + return obj[segment]; + } + } + // Check children for objects that contain the segment + const childrenKey = this.config.propNames.children; + const children = obj[childrenKey]; + if (Array.isArray(children)) { + const matches = children + .map((child) => (segment in child ? child[segment] : undefined)) + .filter((v) => v !== undefined); + return matches.length > 0 ? matches : undefined; + } + return undefined; + } + /** + * Converts a plain JSON object to the XML-like JSON structure. + * Optionally wraps the result in a root element with attributes and namespaces. + * + * @param obj Standard JSON object + * @param root Optional root element configuration (either a string or object with $ keys) + * @returns XML-like JSON object + */ + fromJSONObject(obj, root) { + const wrappedObject = this.wrapObject(obj); + if (typeof root === "string") { + // Root is a simple string: wrap result with this root tag + return { [root]: wrappedObject }; + } + if (root && typeof root === "object") { + // Handle root with config-based keys + const elementName = root.name || "root"; // Default to "root" if no name is provided + const prefix = root[this.config.propNames.prefix] || ""; + const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName; + const result = { + [qualifiedName]: {}, + }; + // Add attributes to the root element if defined + const attrsKey = this.config.propNames.attributes; + if (root[attrsKey] && Array.isArray(root[attrsKey])) { + result[qualifiedName][attrsKey] = root[attrsKey]; + } + // Merge existing children with the new generated children + const childrenKey = this.config.propNames.children; + const children = root[childrenKey] ? root[childrenKey] : []; + result[qualifiedName][childrenKey] = [ + ...children, + { [elementName]: wrappedObject }, + ]; + // Add namespace and prefix if defined + const nsKey = this.config.propNames.namespace; + if (root[nsKey]) { + result[qualifiedName][nsKey] = root[nsKey]; + } + if (prefix && root[nsKey]) { + result[qualifiedName][`xmlns:${prefix}`] = root[nsKey]; + } + return result; + } + // Default behavior if no root is provided + return wrappedObject; + } + /** + * Wraps a standard JSON value in the XML-like JSON structure + * @param value Value to wrap + * @returns Wrapped value + */ + wrapObject(value) { + const valKey = this.config.propNames.value; + const childrenKey = this.config.propNames.children; + if (value === null || + typeof value === "string" || + typeof value === "number" || + typeof value === "boolean") { + return { [valKey]: value }; + } + if (Array.isArray(value)) { + // For arrays, wrap each item and return as a children-style array of repeated elements + return { + [childrenKey]: value.map((item) => { + return this.wrapObject(item); + }), + }; + } + if (typeof value === "object") { + // It's an object: wrap its properties in children + const children = Object.entries(value).map(([key, val]) => ({ + [key]: this.wrapObject(val), + })); + return { [childrenKey]: children }; + } + return undefined; // Fallback for unhandled types + } + /** + * Check if an object is empty + * @param value Value to check + * @returns true if empty + */ + isEmpty(value) { + if (value == null) + return true; + if (Array.isArray(value)) + return value.length === 0; + if (typeof value === "object") + return Object.keys(value).length === 0; + return false; + } + /** + * Safely stringify JSON for debugging + * @param obj Object to stringify + * @param indent Optional indentation level + * @returns JSON string representation + */ + safeStringify(obj, indent = 2) { + try { + return JSON.stringify(obj, null, indent); + } + catch (error) { + return "[Cannot stringify object]"; + } + } + /** + * Deep clone an object + * @param obj Object to clone + * @returns Cloned object + */ + deepClone(obj) { + try { + return JSON.parse(JSON.stringify(obj)); + } + catch (error) { + throw new Error(`Failed to deep clone object: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Deep merge two objects with proper type handling + * @param target Target object + * @param source Source object + * @returns Merged object (target is modified) + */ + deepMerge(target, source) { + if (!source || typeof source !== "object" || source === null) { + return target; + } + if (!target || typeof target !== "object" || target === null) { + return source; + } + Object.keys(source).forEach((key) => { + const sourceValue = source[key]; + const targetValue = target[key]; + // If both source and target values are objects, recursively merge them + if (sourceValue !== null && + targetValue !== null && + typeof sourceValue === "object" && + typeof targetValue === "object" && + !Array.isArray(sourceValue) && + !Array.isArray(targetValue)) { + // Recursively merge the nested objects + target[key] = this.deepMerge(targetValue, sourceValue); + } + else { + // Otherwise just replace the value + target[key] = sourceValue; + } + }); + return target; + } + } + + /** + * Utility for applying value transformations + */ + class TransformUtil { + /** + * Create a new TransformUtil + * @param config Configuration + */ + constructor(config) { + this.config = config; + } + /** + * Apply transforms to a value + * @param value Value to transform + * @param context Transformation context + * @returns Transformed value + */ + applyTransforms(value, context) { + // Skip transformation if no transformers are configured + if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) { + return value; + } + // Apply each transformer in sequence + let transformedValue = value; + for (const transformer of this.config.valueTransforms) { + transformedValue = transformer.process(transformedValue, context); + } + return transformedValue; + } + /** + * Create a transform context + * @param direction Direction of transformation + * @param nodeName Name of the current node + * @param nodeType DOM node type + * @param options Additional context options + * @returns Transform context + */ + createContext(direction, nodeName, nodeType, options = {}) { + return { + direction, + nodeName, + nodeType, + path: options.path || nodeName, + namespace: options.namespace, + prefix: options.prefix, + isAttribute: options.isAttribute || false, + attributeName: options.attributeName, + parent: options.parent, + config: this.config, + }; + } + /** + * Get a user-friendly node type name for debugging + * @param nodeType DOM node type + * @returns String representation of node type + */ + getNodeTypeName(nodeType) { + return DOMAdapter.getNodeTypeName(nodeType); + } + } + + /** + * XMLToJSON Parser for converting XML to JSON + */ + class XMLToJSON { + /** + * Constructor for XMLToJSON + * @param config Configuration options + */ + constructor(config) { + this.config = config; + this.jsonUtil = new JSONUtil(this.config); + this.transformUtil = new TransformUtil(this.config); + } + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + parse(xmlString) { + try { + const xmlDoc = DOMAdapter.parseFromString(xmlString, "text/xml"); + // Check for parsing errors + const errors = xmlDoc.getElementsByTagName("parsererror"); + if (errors.length > 0) { + throw new XJXError(`XML parsing error: ${errors[0].textContent}`); + } + return this.nodeToJson(xmlDoc.documentElement); + } + catch (error) { + throw new XJXError(`Failed to convert XML to JSON: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Convert a DOM node to JSON representation + * @param node DOM node to convert + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the XML tree + * @returns JSON representation of the node + */ + nodeToJson(node, parentContext, path = "") { + const result = {}; + // Handle element nodes + if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { + const element = node; + // Use localName instead of nodeName to strip namespace prefix + const nodeName = element.localName || + element.nodeName.split(":").pop() || + element.nodeName; + // Update the current path + const currentPath = path ? `${path}.${nodeName}` : nodeName; + const nodeObj = {}; + // Create context for this node + const context = this.transformUtil.createContext('xml-to-json', nodeName, node.nodeType, { + path: currentPath, + namespace: element.namespaceURI || undefined, + prefix: element.prefix || undefined, + parent: parentContext + }); + // Process namespaces if enabled + if (this.config.preserveNamespaces) { + const ns = element.namespaceURI; + if (ns) { + nodeObj[this.config.propNames.namespace] = ns; + } + const prefix = element.prefix; + if (prefix) { + nodeObj[this.config.propNames.prefix] = prefix; + } + } + // Process attributes if enabled + if (this.config.preserveAttributes && element.attributes.length > 0) { + const attrs = []; + for (let i = 0; i < element.attributes.length; i++) { + const attr = element.attributes[i]; + // Strip namespace prefix from attribute name + const attrLocalName = attr.localName || attr.name.split(":").pop() || attr.name; + // Create attribute context + const attrContext = this.transformUtil.createContext('xml-to-json', nodeName, node.nodeType, { + path: `${currentPath}.${attrLocalName}`, + namespace: attr.namespaceURI || undefined, + prefix: attr.prefix || undefined, + isAttribute: true, + attributeName: attrLocalName, + parent: context + }); + // Apply transformations to attribute value + const transformedValue = this.transformUtil.applyTransforms(attr.value, attrContext); + // Create attribute object with consistent structure + const attrObj = { + [attrLocalName]: { + [this.config.propNames.value]: transformedValue, + }, + }; + // Add namespace info for attribute if present and enabled + if (this.config.preserveNamespaces) { + // Handle attribute namespace + if (attr.namespaceURI) { + attrObj[attrLocalName][this.config.propNames.namespace] = + attr.namespaceURI; + } + // Handle attribute prefix + if (attr.prefix) { + attrObj[attrLocalName][this.config.propNames.prefix] = + attr.prefix; + } + } + attrs.push(attrObj); + } + if (attrs.length > 0) { + nodeObj[this.config.propNames.attributes] = attrs; + } + } + // Process child nodes + if (element.childNodes.length > 0) { + const children = []; + const childrenKey = this.config.propNames.children; + const valueKey = this.config.propNames.value; + const cdataKey = this.config.propNames.cdata; + const commentsKey = this.config.propNames.comments; + const instructionKey = this.config.propNames.instruction; + const targetKey = this.config.propNames.target; + for (let i = 0; i < element.childNodes.length; i++) { + const child = element.childNodes[i]; + // Text nodes - only process if preserveTextNodes is true + if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) { + if (this.config.preserveTextNodes) { + let text = child.nodeValue || ""; + // Skip whitespace-only text nodes if whitespace preservation is disabled + if (!this.config.preserveWhitespace) { + if (text.trim() === "") { + continue; + } + // Trim the text when preserveWhitespace is false + text = text.trim(); + } + // Create text node context + const textContext = this.transformUtil.createContext('xml-to-json', '#text', child.nodeType, { + path: `${currentPath}.#text`, + parent: context + }); + // Apply transformations to text value + const transformedText = this.transformUtil.applyTransforms(text, textContext); + children.push({ [valueKey]: transformedText }); + } + } + // CDATA sections + else if (child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE && + this.config.preserveCDATA) { + // Create CDATA context + const cdataContext = this.transformUtil.createContext('xml-to-json', '#cdata', child.nodeType, { + path: `${currentPath}.#cdata`, + parent: context + }); + // Apply transformations to CDATA value + const transformedCData = this.transformUtil.applyTransforms(child.nodeValue || "", cdataContext); + children.push({ + [cdataKey]: transformedCData, + }); + } + // Comments + else if (child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE && + this.config.preserveComments) { + children.push({ + [commentsKey]: child.nodeValue || "", + }); + } + // Processing instructions + else if (child.nodeType === + DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE && + this.config.preserveProcessingInstr) { + children.push({ + [instructionKey]: { + [targetKey]: child.nodeName, + [valueKey]: child.nodeValue || "", + }, + }); + } + // Element nodes (recursive) + else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { + children.push(this.nodeToJson(child, context, currentPath)); + } + } + if (children.length > 0) { + nodeObj[childrenKey] = children; + } + } + // Apply compact option - remove empty properties if enabled + if (this.config.outputOptions.compact) { + Object.keys(nodeObj).forEach((key) => { + const cleaned = this.cleanNode(nodeObj[key]); + if (cleaned === undefined) { + delete nodeObj[key]; + } + else { + nodeObj[key] = cleaned; + } + }); + } + result[nodeName] = nodeObj; + } + return result; + } + cleanNode(node) { + if (Array.isArray(node)) { + // Clean each item in the array and filter out empty ones + const cleanedArray = node + .map((item) => this.cleanNode(item)) + .filter((item) => { + return !(item === null || + item === undefined || + (typeof item === "object" && Object.keys(item).length === 0)); + }); + return cleanedArray.length > 0 ? cleanedArray : undefined; + } + else if (typeof node === "object" && node !== null) { + // Clean properties recursively + Object.keys(node).forEach((key) => { + const cleanedChild = this.cleanNode(node[key]); + if (cleanedChild === null || + cleanedChild === undefined || + (Array.isArray(cleanedChild) && cleanedChild.length === 0) || + (typeof cleanedChild === "object" && + Object.keys(cleanedChild).length === 0)) { + delete node[key]; + } + else { + node[key] = cleanedChild; + } + }); + // Handle the special case for nodes with only empty children/attributes + const childrenKey = this.config.propNames.children; + const attrsKey = this.config.propNames.attributes; + const keys = Object.keys(node); + if (keys.every((key) => key === childrenKey || key === attrsKey) && + (node[childrenKey] === undefined || + this.jsonUtil.isEmpty(node[childrenKey])) && + (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))) { + return undefined; + } + return Object.keys(node).length > 0 ? node : undefined; + } + return node; + } + } + + /** + * XMLUtil - Utility functions for XML processing + */ + class XMLUtil { + /** + * Constructor for XMLUtil + * @param config Configuration options + */ + constructor(config) { + this.config = config; + } + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + prettyPrintXml(xmlString) { + const indent = this.config.outputOptions.indent; + const INDENT = " ".repeat(indent); + try { + const doc = DOMAdapter.parseFromString(xmlString, "text/xml"); + const serializer = (node, level = 0) => { + const pad = INDENT.repeat(level); + switch (node.nodeType) { + case DOMAdapter.nodeTypes.ELEMENT_NODE: { + const el = node; + const tagName = el.tagName; + const attrs = Array.from(el.attributes) + .map((a) => `${a.name}="${a.value}"`) + .join(" "); + const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`; + const children = Array.from(el.childNodes); + if (children.length === 0) { + return `${pad}${openTag.replace(/>$/, " />")}\n`; + } + // Single text node: print inline + if (children.length === 0 || + (children.length === 1 && + children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE && + children[0].textContent?.trim() === "")) { + // Empty or whitespace-only + return `${pad}<${tagName}${attrs ? " " + attrs : ""}>\n`; + } + const inner = children + .map((child) => serializer(child, level + 1)) + .join(""); + return `${pad}${openTag}\n${inner}${pad}\n`; + } + case DOMAdapter.nodeTypes.TEXT_NODE: { + const text = node.textContent?.trim(); + return text ? `${pad}${text}\n` : ""; + } + case DOMAdapter.nodeTypes.CDATA_SECTION_NODE: + return `${pad}\n`; + case DOMAdapter.nodeTypes.COMMENT_NODE: + return `${pad}\n`; + case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE: + const pi = node; + return `${pad}\n`; + case DOMAdapter.nodeTypes.DOCUMENT_NODE: + return Array.from(node.childNodes) + .map((child) => serializer(child, level)) + .join(""); + default: + return ""; + } + }; + return serializer(doc).trim(); + } + catch (error) { + throw new XJXError(`Failed to pretty print XML: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Check if XML string is well-formed + * @param xmlString XML string to validate + * @returns Object with validation result and any error messages + */ + validateXML(xmlString) { + try { + const doc = DOMAdapter.parseFromString(xmlString, "text/xml"); + const errors = doc.getElementsByTagName("parsererror"); + if (errors.length > 0) { + return { + isValid: false, + message: errors[0].textContent || "Unknown parsing error", + }; + } + return { isValid: true }; + } + catch (error) { + return { + isValid: false, + message: error instanceof Error ? error.message : String(error), + }; + } + } + /** + * Add XML declaration to a string if missing + * @param xmlString XML string + * @returns XML string with declaration + */ + ensureXMLDeclaration(xmlString) { + if (!xmlString.trim().startsWith("\n' + xmlString; + } + return xmlString; + } + /** + * Escapes special characters in text for safe XML usage. + * @param text Text to escape. + * @returns Escaped XML string. + */ + escapeXML(text) { + if (typeof text !== "string" || text.length === 0) { + return ""; + } + return text.replace(/[&<>"']/g, (char) => { + switch (char) { + case "&": + return "&"; + case "<": + return "<"; + case ">": + return ">"; + case '"': + return """; + case "'": + return "'"; + default: + return char; + } + }); + } + /** + * Unescapes XML entities back to their character equivalents. + * @param text Text with XML entities. + * @returns Unescaped text. + */ + unescapeXML(text) { + if (typeof text !== "string" || text.length === 0) { + return ""; + } + return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => { + switch (entity) { + case "amp": + return "&"; + case "lt": + return "<"; + case "gt": + return ">"; + case "quot": + return '"'; + case "apos": + return "'"; + default: + return match; + } + }); + } + /** + * Extract the namespace prefix from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Prefix or null if no prefix + */ + extractPrefix(qualifiedName) { + const colonIndex = qualifiedName.indexOf(":"); + return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null; + } + /** + * Extract the local name from a qualified name + * @param qualifiedName Qualified name (e.g., "ns:element") + * @returns Local name + */ + extractLocalName(qualifiedName) { + const colonIndex = qualifiedName.indexOf(":"); + return colonIndex > 0 + ? qualifiedName.substring(colonIndex + 1) + : qualifiedName; + } + /** + * Create a qualified name from prefix and local name + * @param prefix Namespace prefix (can be null) + * @param localName Local name + * @returns Qualified name + */ + createQualifiedName(prefix, localName) { + return prefix ? `${prefix}:${localName}` : localName; + } + } + + /** + * JSONToXML for converting JSON to XML + */ + class JSONToXML { + /** + * Constructor for JSONToXML + * @param config Configuration options + */ + constructor(config) { + this.config = config; + this.xmlUtil = new XMLUtil(this.config); + this.transformUtil = new TransformUtil(this.config); + } + /** + * Convert JSON object to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + serialize(jsonObj) { + try { + const doc = DOMAdapter.createDocument(); + const rootElement = this.jsonToNode(jsonObj, doc); + if (rootElement) { + // Handle the temporary root element if it exists + if (doc.documentElement && doc.documentElement.nodeName === "temp") { + doc.replaceChild(rootElement, doc.documentElement); + } + else { + doc.appendChild(rootElement); + } + } + // Add XML declaration if specified + let xmlString = DOMAdapter.serializeToString(doc); + // remove xhtml decl inserted by dom + xmlString = xmlString.replace(' xmlns="http://www.w3.org/1999/xhtml"', ''); + if (this.config.outputOptions.xml.declaration) { + xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString); + } + // Apply pretty printing if enabled + if (this.config.outputOptions.prettyPrint) { + xmlString = this.xmlUtil.prettyPrintXml(xmlString); + } + return xmlString; + } + catch (error) { + throw new XJXError(`Failed to convert JSON to XML: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Convert JSON object to DOM node + * @param jsonObj JSON object to convert + * @param doc Document for creating elements + * @param parentContext Optional parent context for transformation chain + * @param path Current path in the JSON object + * @returns DOM Element + */ + jsonToNode(jsonObj, doc, parentContext, path = "") { + if (!jsonObj || typeof jsonObj !== "object") { + return null; + } + // Get the node name (first key in the object) + const nodeName = Object.keys(jsonObj)[0]; + if (!nodeName) { + return null; + } + const nodeData = jsonObj[nodeName]; + // Update the current path + const currentPath = path ? `${path}.${nodeName}` : nodeName; + // Create element with namespace if available + let element; + const namespaceKey = this.config.propNames.namespace; + const prefixKey = this.config.propNames.prefix; + const ns = nodeData[namespaceKey]; + const prefix = nodeData[prefixKey]; + // Create context for this node + const context = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.ELEMENT_NODE, { + path: currentPath, + namespace: ns, + prefix: prefix, + parent: parentContext + }); + if (ns && this.config.preserveNamespaces) { + if (prefix) { + // Create element with namespace and prefix + element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`); + } + else { + // Create element with namespace but no prefix + element = DOMAdapter.createElementNS(ns, nodeName); + } + } + else { + // Create element without namespace + element = DOMAdapter.createElement(nodeName); + } + // Process attributes if enabled + const attributesKey = this.config.propNames.attributes; + const valueKey = this.config.propNames.value; + if (this.config.preserveAttributes && + nodeData[attributesKey] && + Array.isArray(nodeData[attributesKey])) { + nodeData[attributesKey].forEach((attrObj) => { + const attrName = Object.keys(attrObj)[0]; + if (!attrName) + return; + const attrData = attrObj[attrName]; + // Create attribute context + const attrContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.ELEMENT_NODE, { + path: `${currentPath}.${attrName}`, + namespace: attrData[namespaceKey], + prefix: attrData[prefixKey], + isAttribute: true, + attributeName: attrName, + parent: context + }); + // Apply transformations to attribute value + const transformedValue = this.transformUtil.applyTransforms(attrData[valueKey] || "", attrContext); + const attrNs = attrData[namespaceKey]; + const attrPrefix = attrData[prefixKey]; + // Form qualified name for attribute if it has a prefix + let qualifiedName = attrName; + if (attrPrefix && this.config.preserveNamespaces) { + qualifiedName = `${attrPrefix}:${attrName}`; + } + DOMAdapter.setNamespacedAttribute(element, (attrNs && this.config.preserveNamespaces) ? attrNs : null, qualifiedName, transformedValue); + }); + } + // Process simple text value + if (nodeData[valueKey] !== undefined) { + // Apply transformations to text value + const textContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.TEXT_NODE, { + path: `${currentPath}.#text`, + namespace: ns, + prefix: prefix, + parent: context + }); + const transformedValue = this.transformUtil.applyTransforms(nodeData[valueKey], textContext); + element.textContent = transformedValue; + } + // Process children + const childrenKey = this.config.propNames.children; + const cdataKey = this.config.propNames.cdata; + const commentsKey = this.config.propNames.comments; + const instructionKey = this.config.propNames.instruction; + const targetKey = this.config.propNames.target; + if (nodeData[childrenKey] && + Array.isArray(nodeData[childrenKey])) { + nodeData[childrenKey].forEach((child) => { + // Text nodes + if (child[valueKey] !== undefined && + this.config.preserveTextNodes) { + // Apply transformations to text node + const textContext = this.transformUtil.createContext('json-to-xml', '#text', DOMAdapter.nodeTypes.TEXT_NODE, { + path: `${currentPath}.#text`, + parent: context + }); + const transformedText = this.transformUtil.applyTransforms(child[valueKey], textContext); + element.appendChild(DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))); + } + // CDATA sections + else if (child[cdataKey] !== undefined && + this.config.preserveCDATA) { + // Apply transformations to CDATA + const cdataContext = this.transformUtil.createContext('json-to-xml', '#cdata', DOMAdapter.nodeTypes.CDATA_SECTION_NODE, { + path: `${currentPath}.#cdata`, + parent: context + }); + const transformedCData = this.transformUtil.applyTransforms(child[cdataKey], cdataContext); + element.appendChild(DOMAdapter.createCDATASection(transformedCData)); + } + // Comments + else if (child[commentsKey] !== undefined && + this.config.preserveComments) { + element.appendChild(DOMAdapter.createComment(child[commentsKey])); + } + // Processing instructions + else if (child[instructionKey] !== undefined && + this.config.preserveProcessingInstr) { + const piData = child[instructionKey]; + const target = piData[targetKey]; + const data = piData[valueKey] || ""; + if (target) { + element.appendChild(DOMAdapter.createProcessingInstruction(target, data)); + } + } + // Element nodes (recursive) + else { + const childElement = this.jsonToNode(child, doc, context, currentPath); + if (childElement) { + element.appendChild(childElement); + } + } + }); + } + return element; + } + } + + /** + * Default configuration + */ + const DEFAULT_CONFIG = { + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveWhitespace: false, + preserveAttributes: true, + outputOptions: { + prettyPrint: true, + indent: 2, + compact: true, + json: {}, + xml: { + declaration: true, + }, + }, + propNames: { + namespace: "$ns", + prefix: "$pre", + attributes: "$attr", + value: "$val", + cdata: "$cdata", + comments: "$cmnt", + instruction: "$pi", + target: "$trgt", + children: "$children", + }, + }; + + /** + * XJX - Facade class for XML-JSON conversion operations + */ + class XJX { + /** + * Constructor for XJX utility + * @param config Configuration options + */ + constructor(config = {}) { + // First create a jsonUtil instance with default config to use its methods + this.jsonUtil = new JSONUtil(DEFAULT_CONFIG); + // Create a deep clone of the default config + const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG); + // Deep merge with the provided config + this.config = this.jsonUtil.deepMerge(defaultClone, config); + // Re-initialize jsonUtil with the merged config + this.jsonUtil = new JSONUtil(this.config); + // Initialize other components + this.xmlUtil = new XMLUtil(this.config); + this.xmltojson = new XMLToJSON(this.config); + this.jsontoxml = new JSONToXML(this.config); + } + /** + * Convert XML string to JSON + * @param xmlString XML content as string + * @returns JSON object representing the XML content + */ + xmlToJson(xmlString) { + return this.xmltojson.parse(xmlString); + } + /** + * Convert JSON object back to XML string + * @param jsonObj JSON object to convert + * @returns XML string + */ + jsonToXml(jsonObj) { + return this.jsontoxml.serialize(jsonObj); + } + /** + * Pretty print an XML string + * @param xmlString XML string to format + * @returns Formatted XML string + */ + prettyPrintXml(xmlString) { + return this.xmlUtil.prettyPrintXml(xmlString); + } + /** + * Safely retrieves a value from a JSON object using a dot-separated path. + * @param obj The input JSON object + * @param path The dot-separated path string (e.g., "root.item.description.$val") + * @param fallback Value to return if the path does not resolve + * @returns The value at the specified path or the fallback value + */ + getPath(obj, path, fallback = undefined) { + return this.jsonUtil.getPath(obj, path, fallback); + } + /** + * Validate XML string + * @param xmlString XML string to validate + * @returns Validation result + */ + validateXML(xmlString) { + return this.xmlUtil.validateXML(xmlString); + } + /** + * Add a value transformer to the configuration + * @param transformer Value transformer to add + * @returns This XJX instance for chaining + */ + addTransformer(transformer) { + if (!this.config.valueTransforms) { + this.config.valueTransforms = []; + } + this.config.valueTransforms.push(transformer); + return this; + } + /** + * Removes all value transformers from the configuration + * @returns This XJX instance for chaining + */ + clearTransformers() { + this.config.valueTransforms = []; + return this; + } + /** + * Clean up any resources + */ + cleanup() { + DOMAdapter.cleanup(); + } + } + + /** + * Abstract base class for value transformers + */ + class ValueTransformer { + /** + * Process a value, transforming it if applicable + * @param value Value to potentially transform + * @param context Context including direction and other information + * @returns Transformed value or original if not applicable + */ + process(value, context) { + if (context.direction === 'xml-to-json') { + return this.xmlToJson(value, context); + } + else { + return this.jsonToXml(value, context); + } + } + /** + * Transform a value from XML to JSON representation + * @param value Value from XML + * @param context Transformation context + * @returns Transformed value for JSON + */ + xmlToJson(value, context) { + // Default implementation returns original value + return value; + } + /** + * Transform a value from JSON to XML representation + * @param value Value from JSON + * @param context Transformation context + * @returns Transformed value for XML + */ + jsonToXml(value, context) { + // Default implementation returns original value + return value; + } + } + + // Import locally so you can use it below + + exports.DEFAULT_CONFIG = DEFAULT_CONFIG; + exports.ValueTransformer = ValueTransformer; + exports.XJX = XJX; + exports.XJXError = XJXError; + exports.default = XJX; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); +//# sourceMappingURL=xjx.umd.js.map diff --git a/dist/xjx.umd.js.map b/dist/xjx.umd.js.map new file mode 100644 index 0000000..38f84d3 --- /dev/null +++ b/dist/xjx.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"xjx.umd.js","sources":["../../src/core/types/errors.ts","../../src/core/DOMAdapter.ts","../../src/core/utils/JsonUtils.ts","../../src/core/transforms/TransformUtil.ts","../../src/core/XmlToJsonConverter.ts","../../src/core/utils/XmlUtils.ts","../../src/core/JsonToXmlConverter.ts","../../src/core/config/config.ts","../../src/XJX.ts","../../src/core/transforms/ValueTransformer.ts","../../src/index.ts"],"sourcesContent":["/**\n * Error classes for the XJX library\n */\n\n/**\n * Base error class\n */\nexport class XJXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'XMLToJSONError';\n }\n}\n\n/**\n * Error for XML parsing issues\n */\nexport class XMLParseError extends XJXError {\n constructor(message: string) {\n super(`XML parse error: ${message}`);\n this.name = 'XMLParseError';\n }\n}\n\n/**\n * Error for XML serialization issues\n */\nexport class XMLSerializeError extends XJXError {\n constructor(message: string) {\n super(`XML serialize error: ${message}`);\n this.name = 'XMLSerializeError';\n }\n}\n\n/**\n * Error for environment incompatibility\n */\nexport class EnvironmentError extends XJXError {\n constructor(message: string) {\n super(`Environment error: ${message}`);\n this.name = 'EnvironmentError';\n }\n}\n\n/**\n * Error for invalid configuration\n */\nexport class ConfigurationError extends XJXError {\n constructor(message: string) {\n super(`Configuration error: ${message}`);\n this.name = 'ConfigurationError';\n }\n}","/**\n * DOM Environment provider with unified interface for browser and Node.js\n */\nimport { XJXError } from './types/errors';\n\ninterface NodeTypes {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n}\n\ninterface DOMWindow {\n DOMParser: any;\n XMLSerializer: any;\n Node: {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n };\n document: Document;\n close?: () => void; \n}\n\ninterface JSDOMInstance {\n window: DOMWindow;\n}\n\nexport const DOMAdapter = (() => {\n // Environment-specific DOM implementation\n let domParser: any;\n let xmlSerializer: any;\n let nodeTypes: NodeTypes;\n let docImplementation: any;\n let jsdomInstance: JSDOMInstance | null = null;\n\n try {\n if (typeof window === \"undefined\") {\n // Node.js environment - try JSDOM first\n try {\n const { JSDOM } = require(\"jsdom\");\n jsdomInstance = new JSDOM(\"\", {\n contentType: \"text/xml\",\n }) as JSDOMInstance;\n\n domParser = jsdomInstance.window.DOMParser;\n xmlSerializer = jsdomInstance.window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE,\n TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE,\n CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE,\n COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line\n };\n docImplementation = jsdomInstance.window.document.implementation;\n } catch (jsdomError) {\n // Fall back to xmldom if JSDOM isn't available\n try {\n const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom');\n domParser = DOMParser;\n xmlSerializer = XMLSerializer;\n // Standard DOM node types\n nodeTypes = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n CDATA_SECTION_NODE: 4,\n COMMENT_NODE: 8,\n PROCESSING_INSTRUCTION_NODE: 7,\n DOCUMENT_NODE: 9, \n };\n const implementation = new DOMImplementation();\n docImplementation = implementation;\n } catch (xmldomError) {\n throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`);\n }\n }\n } else {\n // Browser environment\n if (!window.DOMParser) {\n throw new XJXError(\"DOMParser is not available in this environment\");\n }\n\n if (!window.XMLSerializer) {\n throw new XJXError(\"XMLSerializer is not available in this environment\");\n }\n\n domParser = window.DOMParser;\n xmlSerializer = window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: Node.ELEMENT_NODE,\n TEXT_NODE: Node.TEXT_NODE,\n CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE,\n COMMENT_NODE: Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: Node.DOCUMENT_NODE, \n };\n docImplementation = document.implementation;\n }\n } catch (error) {\n throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n return {\n createParser: () => {\n try {\n return new domParser();\n } catch (error) {\n throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createSerializer: () => {\n try {\n return new xmlSerializer();\n } catch (error) {\n throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n nodeTypes,\n \n parseFromString: (xmlString: string, contentType: string = 'text/xml') => {\n try {\n const parser = new domParser();\n return parser.parseFromString(xmlString, contentType);\n } catch (error) {\n throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n serializeToString: (node: Node) => {\n try {\n const serializer = new xmlSerializer();\n return serializer.serializeToString(node);\n } catch (error) {\n throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createDocument: () => {\n try {\n // For browsers, create a document with a root element to avoid issues\n if (typeof window !== \"undefined\") {\n const parser = new domParser();\n return parser.parseFromString('', 'text/xml');\n } else {\n return docImplementation.createDocument(null, null, null);\n }\n } catch (error) {\n throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElement: (tagName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElement(tagName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElement(tagName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElementNS: (namespaceURI: string, qualifiedName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElementNS(namespaceURI, qualifiedName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElementNS(namespaceURI, qualifiedName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createTextNode: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createTextNode(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createTextNode(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createCDATASection: (data: string) => {\n try {\n // For browser compatibility, use document.implementation to create CDATA\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createComment: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createComment(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createComment(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createProcessingInstruction: (target: string, data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n // New helper methods\n \n /**\n * Creates a proper namespace qualified attribute\n */\n setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => {\n try {\n if (namespaceURI) {\n element.setAttributeNS(namespaceURI, qualifiedName, value);\n } else {\n element.setAttribute(qualifiedName, value);\n }\n } catch (error) {\n throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n /**\n * Check if an object is a DOM node\n */\n isNode: (obj: any): boolean => {\n try {\n return obj && typeof obj === 'object' && typeof obj.nodeType === 'number';\n } catch (error) {\n return false;\n }\n },\n \n /**\n * Get DOM node type as string for debugging\n */\n getNodeTypeName: (nodeType: number): string => {\n switch (nodeType) {\n case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE';\n case nodeTypes.TEXT_NODE: return 'TEXT_NODE';\n case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE';\n case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE';\n case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE';\n default: return `UNKNOWN_NODE_TYPE(${nodeType})`;\n }\n },\n \n /**\n * Get all node attributes as an object\n */\n getNodeAttributes: (node: Element): Record => {\n const result: Record = {};\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n result[attr.name] = attr.value;\n }\n return result;\n },\n \n // Cleanup method (mainly for JSDOM)\n cleanup: () => {\n if (jsdomInstance && typeof jsdomInstance.window.close === 'function') {\n jsdomInstance.window.close();\n }\n }\n };\n})();","/**\n * JSONUtil - Utility functions for JSON processing\n */\nimport { Configuration } from \"../types/types\";\n\nexport class JSONUtil {\n private config: Configuration;\n\n /**\n * Constructor for JSONUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * Automatically traverses into children arrays and flattens results.\n *\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns Retrieved value or fallback\n */\n getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n const segments = path.split(\".\");\n let current: any = obj;\n\n for (const segment of segments) {\n if (Array.isArray(current)) {\n // Apply the segment to each array element and flatten results\n const results = current\n .map((item) => this.resolveSegment(item, segment))\n .flat()\n .filter((v) => v !== undefined);\n current = results.length > 0 ? results : undefined;\n } else {\n current = this.resolveSegment(current, segment);\n }\n\n if (current === undefined) return fallback;\n }\n\n // Collapse singleton arrays\n if (Array.isArray(current) && current.length === 1) {\n return current[0];\n }\n\n return current !== undefined ? current : fallback;\n }\n\n /**\n * Resolves a single path segment in the context of a JSON object.\n * Falls back to searching children for matching keys.\n *\n * @param obj The current object\n * @param segment The path segment to resolve\n * @returns Resolved value or undefined\n */\n private resolveSegment(obj: any, segment: string): any {\n if (obj == null || typeof obj !== \"object\") return undefined;\n\n // Direct property access\n if (segment in obj) {\n return obj[segment];\n }\n\n // Check if this is a special property name that matches the config\n if (\n segment === this.config.propNames.value ||\n segment === this.config.propNames.children ||\n segment === this.config.propNames.attributes ||\n segment === this.config.propNames.namespace ||\n segment === this.config.propNames.prefix ||\n segment === this.config.propNames.cdata ||\n segment === this.config.propNames.comments ||\n segment === this.config.propNames.instruction ||\n segment === this.config.propNames.target\n ) {\n const configKey = Object.entries(this.config.propNames).find(\n ([_, value]) => value === segment\n )?.[0];\n\n if (configKey && obj[segment] !== undefined) {\n return obj[segment];\n }\n }\n\n // Check children for objects that contain the segment\n const childrenKey = this.config.propNames.children;\n const children = obj[childrenKey];\n if (Array.isArray(children)) {\n const matches = children\n .map((child) => (segment in child ? child[segment] : undefined))\n .filter((v) => v !== undefined);\n return matches.length > 0 ? matches : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Converts a plain JSON object to the XML-like JSON structure.\n * Optionally wraps the result in a root element with attributes and namespaces.\n *\n * @param obj Standard JSON object\n * @param root Optional root element configuration (either a string or object with $ keys)\n * @returns XML-like JSON object\n */\n fromJSONObject(obj: any, root?: any): any {\n const wrappedObject = this.wrapObject(obj);\n\n if (typeof root === \"string\") {\n // Root is a simple string: wrap result with this root tag\n return { [root]: wrappedObject };\n }\n\n if (root && typeof root === \"object\") {\n // Handle root with config-based keys\n const elementName = root.name || \"root\"; // Default to \"root\" if no name is provided\n const prefix = root[this.config.propNames.prefix] || \"\";\n const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName;\n\n const result: any = {\n [qualifiedName]: {},\n };\n\n // Add attributes to the root element if defined\n const attrsKey = this.config.propNames.attributes;\n if (root[attrsKey] && Array.isArray(root[attrsKey])) {\n result[qualifiedName][attrsKey] = root[attrsKey];\n }\n\n // Merge existing children with the new generated children\n const childrenKey = this.config.propNames.children;\n const children = root[childrenKey] ? root[childrenKey] : [];\n result[qualifiedName][childrenKey] = [\n ...children,\n { [elementName]: wrappedObject },\n ];\n\n // Add namespace and prefix if defined\n const nsKey = this.config.propNames.namespace;\n if (root[nsKey]) {\n result[qualifiedName][nsKey] = root[nsKey];\n }\n\n if (prefix && root[nsKey]) {\n result[qualifiedName][`xmlns:${prefix}`] = root[nsKey];\n }\n\n return result;\n }\n\n // Default behavior if no root is provided\n return wrappedObject;\n }\n\n /**\n * Wraps a standard JSON value in the XML-like JSON structure\n * @param value Value to wrap\n * @returns Wrapped value\n */\n private wrapObject(value: any): any {\n const valKey = this.config.propNames.value;\n const childrenKey = this.config.propNames.children;\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return { [valKey]: value };\n }\n\n if (Array.isArray(value)) {\n // For arrays, wrap each item and return as a children-style array of repeated elements\n return {\n [childrenKey]: value.map((item) => {\n return this.wrapObject(item);\n }),\n };\n }\n\n if (typeof value === \"object\") {\n // It's an object: wrap its properties in children\n const children = Object.entries(value).map(([key, val]) => ({\n [key]: this.wrapObject(val),\n }));\n\n return { [childrenKey]: children };\n }\n\n return undefined; // Fallback for unhandled types\n }\n\n /**\n * Check if an object is empty\n * @param value Value to check\n * @returns true if empty\n */\n isEmpty(value: any): boolean {\n if (value == null) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n }\n\n /**\n * Safely stringify JSON for debugging\n * @param obj Object to stringify\n * @param indent Optional indentation level\n * @returns JSON string representation\n */\n safeStringify(obj: any, indent: number = 2): string {\n try {\n return JSON.stringify(obj, null, indent);\n } catch (error) {\n return \"[Cannot stringify object]\";\n }\n }\n\n /**\n * Deep clone an object\n * @param obj Object to clone\n * @returns Cloned object\n */\n deepClone(obj: any): any {\n try {\n return JSON.parse(JSON.stringify(obj));\n } catch (error) {\n throw new Error(\n `Failed to deep clone object: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Deep merge two objects with proper type handling\n * @param target Target object\n * @param source Source object\n * @returns Merged object (target is modified)\n */\n deepMerge(target: T, source: Partial): T {\n if (!source || typeof source !== \"object\" || source === null) {\n return target;\n }\n\n if (!target || typeof target !== \"object\" || target === null) {\n return source as unknown as T;\n }\n\n Object.keys(source).forEach((key) => {\n const sourceValue = source[key as keyof Partial];\n const targetValue = target[key as keyof T];\n\n // If both source and target values are objects, recursively merge them\n if (\n sourceValue !== null &&\n targetValue !== null &&\n typeof sourceValue === \"object\" &&\n typeof targetValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n !Array.isArray(targetValue)\n ) {\n // Recursively merge the nested objects\n (target as any)[key] = this.deepMerge(targetValue, sourceValue as any);\n } else {\n // Otherwise just replace the value\n (target as any)[key] = sourceValue;\n }\n });\n\n return target;\n }\n}\n","/**\n * Utilities for applying value transformations\n */\nimport { Configuration } from '../types/types';\nimport { TransformContext, TransformDirection } from './ValueTransformer';\nimport { DOMAdapter } from '../DOMAdapter';\n\n/**\n * Utility for applying value transformations\n */\nexport class TransformUtil {\n private config: Configuration;\n\n /**\n * Create a new TransformUtil\n * @param config Configuration\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Apply transforms to a value\n * @param value Value to transform\n * @param context Transformation context\n * @returns Transformed value\n */\n applyTransforms(value: any, context: TransformContext): any {\n // Skip transformation if no transformers are configured\n if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) {\n return value;\n }\n\n // Apply each transformer in sequence\n let transformedValue = value;\n for (const transformer of this.config.valueTransforms) {\n transformedValue = transformer.process(transformedValue, context);\n }\n\n return transformedValue;\n }\n\n /**\n * Create a transform context\n * @param direction Direction of transformation\n * @param nodeName Name of the current node\n * @param nodeType DOM node type\n * @param options Additional context options\n * @returns Transform context\n */\n createContext(\n direction: TransformDirection,\n nodeName: string,\n nodeType: number,\n options: {\n path?: string;\n namespace?: string;\n prefix?: string;\n isAttribute?: boolean;\n attributeName?: string;\n parent?: TransformContext;\n } = {}\n ): TransformContext {\n return {\n direction,\n nodeName,\n nodeType,\n path: options.path || nodeName,\n namespace: options.namespace,\n prefix: options.prefix,\n isAttribute: options.isAttribute || false,\n attributeName: options.attributeName,\n parent: options.parent,\n config: this.config,\n };\n }\n\n /**\n * Get a user-friendly node type name for debugging\n * @param nodeType DOM node type\n * @returns String representation of node type\n */\n getNodeTypeName(nodeType: number): string {\n return DOMAdapter.getNodeTypeName(nodeType);\n }\n}","/**\n * XMLToJSON class for converting XML to JSON with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { JSONUtil } from \"./utils/JsonUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * XMLToJSON Parser for converting XML to JSON\n */\nexport class XMLToJSON {\n private config: Configuration;\n private jsonUtil: JSONUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for XMLToJSON\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.jsonUtil = new JSONUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public parse(xmlString: string): Record {\n try {\n const xmlDoc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n // Check for parsing errors\n const errors = xmlDoc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n throw new XJXError(`XML parsing error: ${errors[0].textContent}`);\n }\n\n return this.nodeToJson(xmlDoc.documentElement);\n } catch (error) {\n throw new XJXError(\n `Failed to convert XML to JSON: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert a DOM node to JSON representation\n * @param node DOM node to convert\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the XML tree\n * @returns JSON representation of the node\n */\n private nodeToJson(node: Node, parentContext?: TransformContext, path: string = \"\"): Record {\n const result: Record = {};\n\n // Handle element nodes\n if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n const element = node as Element;\n // Use localName instead of nodeName to strip namespace prefix\n const nodeName =\n element.localName ||\n element.nodeName.split(\":\").pop() ||\n element.nodeName;\n\n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n const nodeObj: Record = {};\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: currentPath,\n namespace: element.namespaceURI || undefined,\n prefix: element.prefix || undefined,\n parent: parentContext\n }\n );\n\n // Process namespaces if enabled\n if (this.config.preserveNamespaces) {\n const ns = element.namespaceURI;\n if (ns) {\n nodeObj[this.config.propNames.namespace] = ns;\n }\n\n const prefix = element.prefix;\n if (prefix) {\n nodeObj[this.config.propNames.prefix] = prefix;\n }\n }\n\n // Process attributes if enabled\n if (this.config.preserveAttributes && element.attributes.length > 0) {\n const attrs: Array> = [];\n\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n // Strip namespace prefix from attribute name\n const attrLocalName =\n attr.localName || attr.name.split(\":\").pop() || attr.name;\n\n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: `${currentPath}.${attrLocalName}`,\n namespace: attr.namespaceURI || undefined,\n prefix: attr.prefix || undefined,\n isAttribute: true,\n attributeName: attrLocalName,\n parent: context\n }\n );\n\n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attr.value,\n attrContext\n );\n\n // Create attribute object with consistent structure\n const attrObj: Record = {\n [attrLocalName]: {\n [this.config.propNames.value]: transformedValue,\n },\n };\n\n // Add namespace info for attribute if present and enabled\n if (this.config.preserveNamespaces) {\n // Handle attribute namespace\n if (attr.namespaceURI) {\n attrObj[attrLocalName][this.config.propNames.namespace] =\n attr.namespaceURI;\n }\n\n // Handle attribute prefix\n if (attr.prefix) {\n attrObj[attrLocalName][this.config.propNames.prefix] =\n attr.prefix;\n }\n }\n\n attrs.push(attrObj);\n }\n\n if (attrs.length > 0) {\n nodeObj[this.config.propNames.attributes] = attrs;\n }\n }\n\n // Process child nodes\n if (element.childNodes.length > 0) {\n const children: Array> = [];\n const childrenKey = this.config.propNames.children;\n const valueKey = this.config.propNames.value;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n\n // Text nodes - only process if preserveTextNodes is true\n if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) {\n if (this.config.preserveTextNodes) {\n let text = child.nodeValue || \"\";\n\n // Skip whitespace-only text nodes if whitespace preservation is disabled\n if (!this.config.preserveWhitespace) {\n if (text.trim() === \"\") {\n continue;\n }\n // Trim the text when preserveWhitespace is false\n text = text.trim();\n }\n\n // Create text node context\n const textContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#text',\n child.nodeType,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n\n // Apply transformations to text value\n const transformedText = this.transformUtil.applyTransforms(\n text,\n textContext\n );\n\n children.push({ [valueKey]: transformedText });\n }\n }\n // CDATA sections\n else if (\n child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE &&\n this.config.preserveCDATA\n ) {\n // Create CDATA context\n const cdataContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#cdata',\n child.nodeType,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n\n // Apply transformations to CDATA value\n const transformedCData = this.transformUtil.applyTransforms(\n child.nodeValue || \"\",\n cdataContext\n );\n\n children.push({\n [cdataKey]: transformedCData,\n });\n }\n // Comments\n else if (\n child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE &&\n this.config.preserveComments\n ) {\n children.push({\n [commentsKey]: child.nodeValue || \"\",\n });\n }\n // Processing instructions\n else if (\n child.nodeType ===\n DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE &&\n this.config.preserveProcessingInstr\n ) {\n children.push({\n [instructionKey]: {\n [targetKey]: child.nodeName,\n [valueKey]: child.nodeValue || \"\",\n },\n });\n }\n // Element nodes (recursive)\n else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n children.push(this.nodeToJson(child, context, currentPath));\n }\n }\n\n if (children.length > 0) {\n nodeObj[childrenKey] = children;\n }\n }\n\n // Apply compact option - remove empty properties if enabled\n if (this.config.outputOptions.compact) {\n Object.keys(nodeObj).forEach((key) => {\n const cleaned = this.cleanNode(nodeObj[key]);\n if (cleaned === undefined) {\n delete nodeObj[key];\n } else {\n nodeObj[key] = cleaned;\n }\n });\n }\n\n result[nodeName] = nodeObj;\n }\n\n return result;\n }\n\n private cleanNode(node: any): any {\n if (Array.isArray(node)) {\n // Clean each item in the array and filter out empty ones\n const cleanedArray = node\n .map((item) => this.cleanNode(item))\n .filter((item) => {\n return !(\n item === null ||\n item === undefined ||\n (typeof item === \"object\" && Object.keys(item).length === 0)\n );\n });\n return cleanedArray.length > 0 ? cleanedArray : undefined;\n } else if (typeof node === \"object\" && node !== null) {\n // Clean properties recursively\n Object.keys(node).forEach((key) => {\n const cleanedChild = this.cleanNode(node[key]);\n if (\n cleanedChild === null ||\n cleanedChild === undefined ||\n (Array.isArray(cleanedChild) && cleanedChild.length === 0) ||\n (typeof cleanedChild === \"object\" &&\n Object.keys(cleanedChild).length === 0)\n ) {\n delete node[key];\n } else {\n node[key] = cleanedChild;\n }\n });\n\n // Handle the special case for nodes with only empty children/attributes\n const childrenKey = this.config.propNames.children;\n const attrsKey = this.config.propNames.attributes;\n const keys = Object.keys(node);\n if (\n keys.every((key) => key === childrenKey || key === attrsKey) &&\n (node[childrenKey] === undefined ||\n this.jsonUtil.isEmpty(node[childrenKey])) &&\n (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))\n ) {\n return undefined;\n }\n\n return Object.keys(node).length > 0 ? node : undefined;\n }\n\n return node;\n }\n}","/**\n * XMLUtil - Utility functions for XML processing\n */\nimport { XJXError } from \"../types/errors\";\nimport { DOMAdapter } from \"../DOMAdapter\";\nimport { Configuration } from \"../types/types\";\n\nexport class XMLUtil {\n private config: Configuration;\n\n /**\n * Constructor for XMLUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n prettyPrintXml(xmlString: string): string {\n const indent = this.config.outputOptions.indent;\n const INDENT = \" \".repeat(indent);\n\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n const serializer = (node: Node, level = 0): string => {\n const pad = INDENT.repeat(level);\n\n switch (node.nodeType) {\n case DOMAdapter.nodeTypes.ELEMENT_NODE: {\n const el = node as Element;\n const tagName = el.tagName;\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`;\n\n const children = Array.from(el.childNodes);\n\n if (children.length === 0) {\n return `${pad}${openTag.replace(/>$/, \" />\")}\\n`;\n }\n\n // Single text node: print inline\n if (\n children.length === 0 ||\n (children.length === 1 &&\n children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE &&\n children[0].textContent?.trim() === \"\")\n ) {\n // Empty or whitespace-only\n return `${pad}<${tagName}${attrs ? \" \" + attrs : \"\"}>\\n`;\n }\n\n const inner = children\n .map((child) => serializer(child, level + 1))\n .join(\"\");\n return `${pad}${openTag}\\n${inner}${pad}\\n`;\n }\n\n case DOMAdapter.nodeTypes.TEXT_NODE: {\n const text = node.textContent?.trim();\n return text ? `${pad}${text}\\n` : \"\";\n }\n\n case DOMAdapter.nodeTypes.CDATA_SECTION_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.COMMENT_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE:\n const pi = node as ProcessingInstruction;\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.DOCUMENT_NODE:\n return Array.from(node.childNodes)\n .map((child) => serializer(child, level))\n .join(\"\");\n\n default:\n return \"\";\n }\n };\n\n return serializer(doc).trim();\n } catch (error) {\n throw new XJXError(\n `Failed to pretty print XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Check if XML string is well-formed\n * @param xmlString XML string to validate\n * @returns Object with validation result and any error messages\n */\n validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n const errors = doc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n return {\n isValid: false,\n message: errors[0].textContent || \"Unknown parsing error\",\n };\n }\n return { isValid: true };\n } catch (error) {\n return {\n isValid: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Add XML declaration to a string if missing\n * @param xmlString XML string\n * @returns XML string with declaration\n */\n ensureXMLDeclaration(xmlString: string): string {\n if (!xmlString.trim().startsWith(\"\\n' + xmlString;\n }\n return xmlString;\n }\n\n /**\n * Escapes special characters in text for safe XML usage.\n * @param text Text to escape.\n * @returns Escaped XML string.\n */\n escapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&\";\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case '\"':\n return \""\";\n case \"'\":\n return \"'\";\n default:\n return char;\n }\n });\n }\n\n /**\n * Unescapes XML entities back to their character equivalents.\n * @param text Text with XML entities.\n * @returns Unescaped text.\n */\n unescapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => {\n switch (entity) {\n case \"amp\":\n return \"&\";\n case \"lt\":\n return \"<\";\n case \"gt\":\n return \">\";\n case \"quot\":\n return '\"';\n case \"apos\":\n return \"'\";\n default:\n return match;\n }\n });\n }\n\n /**\n * Extract the namespace prefix from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Prefix or null if no prefix\n */\n extractPrefix(qualifiedName: string): string | null {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null;\n }\n\n /**\n * Extract the local name from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Local name\n */\n extractLocalName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0\n ? qualifiedName.substring(colonIndex + 1)\n : qualifiedName;\n }\n\n /**\n * Create a qualified name from prefix and local name\n * @param prefix Namespace prefix (can be null)\n * @param localName Local name\n * @returns Qualified name\n */\n createQualifiedName(prefix: string | null, localName: string): string {\n return prefix ? `${prefix}:${localName}` : localName;\n }\n}","/**\n * JSONToXML class for converting JSON to XML with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { XMLUtil } from \"./utils/XmlUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * JSONToXML for converting JSON to XML\n */\nexport class JSONToXML {\n private config: Configuration;\n private xmlUtil: XMLUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for JSONToXML\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.xmlUtil = new XMLUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert JSON object to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public serialize(jsonObj: Record): string {\n try {\n const doc = DOMAdapter.createDocument();\n const rootElement = this.jsonToNode(jsonObj, doc);\n\n if (rootElement) {\n // Handle the temporary root element if it exists\n if (doc.documentElement && doc.documentElement.nodeName === \"temp\") {\n doc.replaceChild(rootElement, doc.documentElement);\n } else {\n doc.appendChild(rootElement);\n }\n }\n\n // Add XML declaration if specified\n let xmlString = DOMAdapter.serializeToString(doc);\n\n // remove xhtml decl inserted by dom\n xmlString = xmlString.replace(' xmlns=\"http://www.w3.org/1999/xhtml\"', '');\n\n if (this.config.outputOptions.xml.declaration) {\n xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString);\n }\n\n // Apply pretty printing if enabled\n if (this.config.outputOptions.prettyPrint) {\n xmlString = this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n return xmlString;\n } catch (error) {\n throw new XJXError(\n `Failed to convert JSON to XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert JSON object to DOM node\n * @param jsonObj JSON object to convert\n * @param doc Document for creating elements\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the JSON object\n * @returns DOM Element\n */\n private jsonToNode(\n jsonObj: Record,\n doc: Document,\n parentContext?: TransformContext,\n path: string = \"\"\n ): Element | null {\n if (!jsonObj || typeof jsonObj !== \"object\") {\n return null;\n }\n\n // Get the node name (first key in the object)\n const nodeName = Object.keys(jsonObj)[0];\n if (!nodeName) {\n return null;\n }\n\n const nodeData = jsonObj[nodeName];\n \n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n // Create element with namespace if available\n let element: Element;\n const namespaceKey = this.config.propNames.namespace;\n const prefixKey = this.config.propNames.prefix;\n const ns = nodeData[namespaceKey];\n const prefix = nodeData[prefixKey];\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: currentPath,\n namespace: ns,\n prefix: prefix,\n parent: parentContext\n }\n );\n\n if (ns && this.config.preserveNamespaces) {\n if (prefix) {\n // Create element with namespace and prefix\n element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`);\n } else {\n // Create element with namespace but no prefix\n element = DOMAdapter.createElementNS(ns, nodeName);\n }\n } else {\n // Create element without namespace\n element = DOMAdapter.createElement(nodeName);\n }\n\n // Process attributes if enabled\n const attributesKey = this.config.propNames.attributes;\n const valueKey = this.config.propNames.value;\n if (\n this.config.preserveAttributes &&\n nodeData[attributesKey] &&\n Array.isArray(nodeData[attributesKey])\n ) {\n nodeData[attributesKey].forEach(\n (attrObj: Record) => {\n const attrName = Object.keys(attrObj)[0];\n if (!attrName) return;\n\n const attrData = attrObj[attrName];\n \n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: `${currentPath}.${attrName}`,\n namespace: attrData[namespaceKey],\n prefix: attrData[prefixKey],\n isAttribute: true,\n attributeName: attrName,\n parent: context\n }\n );\n \n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attrData[valueKey] || \"\",\n attrContext\n );\n \n const attrNs = attrData[namespaceKey];\n const attrPrefix = attrData[prefixKey];\n\n // Form qualified name for attribute if it has a prefix\n let qualifiedName = attrName;\n if (attrPrefix && this.config.preserveNamespaces) {\n qualifiedName = `${attrPrefix}:${attrName}`;\n }\n\n DOMAdapter.setNamespacedAttribute(\n element, \n (attrNs && this.config.preserveNamespaces) ? attrNs : null, \n qualifiedName, \n transformedValue\n );\n }\n );\n }\n\n // Process simple text value\n if (nodeData[valueKey] !== undefined) {\n // Apply transformations to text value\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n namespace: ns,\n prefix: prefix,\n parent: context\n }\n );\n \n const transformedValue = this.transformUtil.applyTransforms(\n nodeData[valueKey],\n textContext\n );\n \n element.textContent = transformedValue;\n }\n\n // Process children\n const childrenKey = this.config.propNames.children;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n if (\n nodeData[childrenKey] &&\n Array.isArray(nodeData[childrenKey])\n ) {\n nodeData[childrenKey].forEach(\n (child: Record) => {\n // Text nodes\n if (\n child[valueKey] !== undefined &&\n this.config.preserveTextNodes\n ) {\n // Apply transformations to text node\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#text',\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n \n const transformedText = this.transformUtil.applyTransforms(\n child[valueKey],\n textContext\n );\n \n element.appendChild(\n DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))\n );\n }\n // CDATA sections\n else if (\n child[cdataKey] !== undefined &&\n this.config.preserveCDATA\n ) {\n // Apply transformations to CDATA\n const cdataContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#cdata',\n DOMAdapter.nodeTypes.CDATA_SECTION_NODE,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n \n const transformedCData = this.transformUtil.applyTransforms(\n child[cdataKey],\n cdataContext\n );\n \n element.appendChild(\n DOMAdapter.createCDATASection(\n transformedCData\n )\n );\n }\n // Comments\n else if (\n child[commentsKey] !== undefined &&\n this.config.preserveComments\n ) {\n element.appendChild(\n DOMAdapter.createComment(\n child[commentsKey]\n )\n );\n }\n // Processing instructions\n else if (\n child[instructionKey] !== undefined &&\n this.config.preserveProcessingInstr\n ) {\n const piData = child[instructionKey];\n const target = piData[targetKey];\n const data = piData[valueKey] || \"\";\n\n if (target) {\n element.appendChild(\n DOMAdapter.createProcessingInstruction(target, data)\n );\n }\n }\n // Element nodes (recursive)\n else {\n const childElement = this.jsonToNode(child, doc, context, currentPath);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n }\n );\n }\n\n return element;\n }\n}","/**\n * Default configuration for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: Configuration = {\n preserveNamespaces: true,\n preserveComments: true,\n preserveProcessingInstr: true,\n preserveCDATA: true,\n preserveTextNodes: true,\n preserveWhitespace: false,\n preserveAttributes: true,\n\n outputOptions: {\n prettyPrint: true,\n indent: 2,\n compact: true,\n json: {},\n xml: {\n declaration: true,\n },\n },\n\n propNames: {\n namespace: \"$ns\",\n prefix: \"$pre\",\n attributes: \"$attr\",\n value: \"$val\",\n cdata: \"$cdata\",\n comments: \"$cmnt\",\n instruction: \"$pi\", \n target: \"$trgt\", \n children: \"$children\",\n },\n};","/**\n * XJX - Facade class for XML-JSON conversion operations\n */\nimport { XMLToJSON } from \"./core/XmlToJsonConverter\";\nimport { JSONToXML } from \"./core/JsonToXmlConverter\";\nimport { Configuration } from \"./core/types/types\";\nimport { DEFAULT_CONFIG } from \"./core/config/config\";\nimport { DOMAdapter } from \"./core/DOMAdapter\";\nimport { XMLUtil } from \"./core/utils/XmlUtils\";\nimport { JSONUtil } from \"./core/utils/JsonUtils\";\nimport { ValueTransformer } from \"./core/transforms\";\n\nexport class XJX {\n private config: Configuration;\n private xmltojson: XMLToJSON;\n private jsontoxml: JSONToXML;\n private jsonUtil: JSONUtil;\n private xmlUtil: XMLUtil;\n\n /**\n * Constructor for XJX utility\n * @param config Configuration options\n */\n constructor(config: Partial = {}) {\n // First create a jsonUtil instance with default config to use its methods\n this.jsonUtil = new JSONUtil(DEFAULT_CONFIG);\n\n // Create a deep clone of the default config\n const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG);\n\n // Deep merge with the provided config\n this.config = this.jsonUtil.deepMerge(defaultClone, config);\n\n // Re-initialize jsonUtil with the merged config\n this.jsonUtil = new JSONUtil(this.config);\n\n // Initialize other components\n this.xmlUtil = new XMLUtil(this.config);\n this.xmltojson = new XMLToJSON(this.config);\n this.jsontoxml = new JSONToXML(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public xmlToJson(xmlString: string): Record {\n return this.xmltojson.parse(xmlString);\n }\n\n /**\n * Convert JSON object back to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public jsonToXml(jsonObj: Record): string {\n return this.jsontoxml.serialize(jsonObj);\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n public prettyPrintXml(xmlString: string): string {\n return this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns The value at the specified path or the fallback value\n */\n public getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n return this.jsonUtil.getPath(obj, path, fallback);\n }\n\n /**\n * Validate XML string\n * @param xmlString XML string to validate\n * @returns Validation result\n */\n public validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n return this.xmlUtil.validateXML(xmlString);\n }\n\n /**\n * Add a value transformer to the configuration\n * @param transformer Value transformer to add\n * @returns This XJX instance for chaining\n */\n public addTransformer(transformer: ValueTransformer): XJX {\n if (!this.config.valueTransforms) {\n this.config.valueTransforms = [];\n }\n this.config.valueTransforms.push(transformer);\n return this;\n }\n\n /**\n * Removes all value transformers from the configuration\n * @returns This XJX instance for chaining\n */\n public clearTransformers(): XJX {\n this.config.valueTransforms = [];\n return this;\n }\n\n /**\n * Clean up any resources\n */\n public cleanup(): void {\n DOMAdapter.cleanup();\n }\n}","/**\n * Value transformation types and base class for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Direction of the transformation\n */\nexport type TransformDirection = 'xml-to-json' | 'json-to-xml';\n\n/**\n * Context provided to value transformers\n */\nexport interface TransformContext {\n // Core transformation info\n direction: TransformDirection; // Direction of the current transformation\n \n // Node information\n nodeName: string; // Name of the current node\n nodeType: number; // DOM node type (element, text, etc.)\n namespace?: string; // Namespace URI if available\n prefix?: string; // Namespace prefix if available\n \n // Structure information\n path: string; // Dot-notation path to current node\n isAttribute: boolean; // Whether the current value is from an attribute\n attributeName?: string; // Name of attribute if isAttribute is true\n \n // Parent context (creates a chain)\n parent?: TransformContext; // Reference to parent context for traversal\n \n // Configuration reference\n config: Configuration; // Reference to the current configuration\n}\n\n/**\n * Abstract base class for value transformers\n */\nexport abstract class ValueTransformer {\n /**\n * Process a value, transforming it if applicable\n * @param value Value to potentially transform\n * @param context Context including direction and other information\n * @returns Transformed value or original if not applicable\n */\n process(value: any, context: TransformContext): any {\n if (context.direction === 'xml-to-json') {\n return this.xmlToJson(value, context);\n } else {\n return this.jsonToXml(value, context);\n }\n }\n\n /**\n * Transform a value from XML to JSON representation\n * @param value Value from XML\n * @param context Transformation context\n * @returns Transformed value for JSON\n */\n protected xmlToJson(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n\n /**\n * Transform a value from JSON to XML representation\n * @param value Value from JSON\n * @param context Transformation context\n * @returns Transformed value for XML\n */\n protected jsonToXml(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n}","// Import locally so you can use it below\nimport { XJX } from './XJX';\n\n// Core components\nexport { XJX };\nexport { Configuration } from './core/types/types';\nexport { DEFAULT_CONFIG } from './core/config/config';\n\n// Error handling\nexport { XJXError } from './core/types/errors';\n\n// Allow custom transformers\nexport { ValueTransformer } from './core/transforms/ValueTransformer';\n\n// Default export\nexport default XJX;"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f086295..67550a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "rollup": "^3.29.5", "rollup-plugin-dts": "^5.3.1", "rollup-plugin-filesize": "^10.0.0", + "rollup-plugin-gzip": "^4.0.1", "rollup-plugin-visualizer": "^5.14.0", "ts-jest": "^29.1.1", "typedoc": "^0.24.1", @@ -8057,6 +8058,19 @@ "node": ">=16.0.0" } }, + "node_modules/rollup-plugin-gzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-gzip/-/rollup-plugin-gzip-4.0.1.tgz", + "integrity": "sha512-HVukJ5vwTxgzKaNeKCNEqFRQ+/T/j/3zqoUaCN3VGTt8/Mn7Wu2nMCE8VBIDubjM5U+QGgiWs6fYysn63JZY1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "rollup": ">=2.0.0" + } + }, "node_modules/rollup-plugin-visualizer": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.14.0.tgz", diff --git a/package.json b/package.json index 0f89bcc..7c815d3 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "rollup": "^3.29.5", "rollup-plugin-dts": "^5.3.1", "rollup-plugin-filesize": "^10.0.0", + "rollup-plugin-gzip": "^4.0.1", "rollup-plugin-visualizer": "^5.14.0", "ts-jest": "^29.1.1", "typedoc": "^0.24.1", @@ -107,5 +108,6 @@ }, "engines": { "node": ">=14.16.0" - } + }, + "sideEffects": false } diff --git a/src/XJX.ts b/src/XJX.ts index 6803c27..1afb925 100644 --- a/src/XJX.ts +++ b/src/XJX.ts @@ -8,10 +8,7 @@ import { DEFAULT_CONFIG } from "./core/config/config"; import { DOMAdapter } from "./core/DOMAdapter"; import { XMLUtil } from "./core/utils/XmlUtils"; import { JSONUtil } from "./core/utils/JsonUtils"; -import { ValueTransformer } from "./core/transforms/ValueTransformer"; -import { BooleanTransformer } from "./core/transforms/BooleanTransformer"; -import { NumberTransformer } from "./core/transforms/NumberTransformer"; -import { StringReplaceTransformer } from "./core/transforms/StringReplaceTransformer"; +import { ValueTransformer } from "./core/transforms"; export class XJX { private config: Configuration; @@ -119,39 +116,6 @@ export class XJX { return this; } - /** - * Create a new boolean transformer and add it to the configuration - * @param options Options for the transformer - * @returns The created transformer instance - */ - public createBooleanTransformer(options = {}): BooleanTransformer { - const transformer = new BooleanTransformer(options); - this.addTransformer(transformer); - return transformer; - } - - /** - * Create a new number transformer and add it to the configuration - * @param options Options for the transformer - * @returns The created transformer instance - */ - public createNumberTransformer(options = {}): NumberTransformer { - const transformer = new NumberTransformer(options); - this.addTransformer(transformer); - return transformer; - } - - /** - * Create a new string replace transformer and add it to the configuration - * @param options Options for the transformer - * @returns The created transformer instance - */ - public createStringReplaceTransformer(options = {}): StringReplaceTransformer { - const transformer = new StringReplaceTransformer(options); - this.addTransformer(transformer); - return transformer; - } - /** * Clean up any resources */ diff --git a/src/core/DOMAdapter.ts b/src/core/DOMAdapter.ts index c1a3b4b..39727f2 100644 --- a/src/core/DOMAdapter.ts +++ b/src/core/DOMAdapter.ts @@ -1,7 +1,7 @@ /** * DOM Environment provider with unified interface for browser and Node.js */ -import { XMLToJSONError } from './types/Errors'; +import { XJXError } from './types/errors'; interface NodeTypes { ELEMENT_NODE: number; @@ -77,17 +77,17 @@ export const DOMAdapter = (() => { const implementation = new DOMImplementation(); docImplementation = implementation; } catch (xmldomError) { - throw new XMLToJSONError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`); + throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`); } } } else { // Browser environment if (!window.DOMParser) { - throw new XMLToJSONError("DOMParser is not available in this environment"); + throw new XJXError("DOMParser is not available in this environment"); } if (!window.XMLSerializer) { - throw new XMLToJSONError("XMLSerializer is not available in this environment"); + throw new XJXError("XMLSerializer is not available in this environment"); } domParser = window.DOMParser; @@ -103,7 +103,7 @@ export const DOMAdapter = (() => { docImplementation = document.implementation; } } catch (error) { - throw new XMLToJSONError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`); } return { @@ -111,7 +111,7 @@ export const DOMAdapter = (() => { try { return new domParser(); } catch (error) { - throw new XMLToJSONError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -119,7 +119,7 @@ export const DOMAdapter = (() => { try { return new xmlSerializer(); } catch (error) { - throw new XMLToJSONError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -130,7 +130,7 @@ export const DOMAdapter = (() => { const parser = new domParser(); return parser.parseFromString(xmlString, contentType); } catch (error) { - throw new XMLToJSONError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -139,7 +139,7 @@ export const DOMAdapter = (() => { const serializer = new xmlSerializer(); return serializer.serializeToString(node); } catch (error) { - throw new XMLToJSONError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -153,7 +153,7 @@ export const DOMAdapter = (() => { return docImplementation.createDocument(null, null, null); } } catch (error) { - throw new XMLToJSONError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -166,7 +166,7 @@ export const DOMAdapter = (() => { return doc.createElement(tagName); } } catch (error) { - throw new XMLToJSONError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -179,7 +179,7 @@ export const DOMAdapter = (() => { return doc.createElementNS(namespaceURI, qualifiedName); } } catch (error) { - throw new XMLToJSONError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -192,7 +192,7 @@ export const DOMAdapter = (() => { return doc.createTextNode(data); } } catch (error) { - throw new XMLToJSONError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -207,7 +207,7 @@ export const DOMAdapter = (() => { return doc.createCDATASection(data); } } catch (error) { - throw new XMLToJSONError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -220,7 +220,7 @@ export const DOMAdapter = (() => { return doc.createComment(data); } } catch (error) { - throw new XMLToJSONError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -234,7 +234,7 @@ export const DOMAdapter = (() => { return doc.createProcessingInstruction(target, data); } } catch (error) { - throw new XMLToJSONError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`); } }, @@ -251,7 +251,7 @@ export const DOMAdapter = (() => { element.setAttribute(qualifiedName, value); } } catch (error) { - throw new XMLToJSONError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`); + throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`); } }, diff --git a/src/core/JsonToXmlConverter.ts b/src/core/JsonToXmlConverter.ts index 3935a37..12429b7 100644 --- a/src/core/JsonToXmlConverter.ts +++ b/src/core/JsonToXmlConverter.ts @@ -2,7 +2,7 @@ * JSONToXML class for converting JSON to XML with consistent namespace handling */ import { Configuration } from "./types/types"; -import { XMLToJSONError } from "./types/Errors"; +import { XJXError } from "./types/errors"; import { DOMAdapter } from "./DOMAdapter"; import { XMLUtil } from "./utils/XmlUtils"; import { TransformUtil } from "./transforms/TransformUtil"; @@ -62,7 +62,7 @@ export class JSONToXML { return xmlString; } catch (error) { - throw new XMLToJSONError( + throw new XJXError( `Failed to convert JSON to XML: ${ error instanceof Error ? error.message : String(error) }` diff --git a/src/core/XmlToJsonConverter.ts b/src/core/XmlToJsonConverter.ts index 9254254..b24f7ff 100644 --- a/src/core/XmlToJsonConverter.ts +++ b/src/core/XmlToJsonConverter.ts @@ -2,7 +2,7 @@ * XMLToJSON class for converting XML to JSON with consistent namespace handling */ import { Configuration } from "./types/types"; -import { XMLToJSONError } from "./types/Errors"; +import { XJXError } from "./types/errors"; import { DOMAdapter } from "./DOMAdapter"; import { JSONUtil } from "./utils/JsonUtils"; import { TransformUtil } from "./transforms/TransformUtil"; @@ -38,12 +38,12 @@ export class XMLToJSON { // Check for parsing errors const errors = xmlDoc.getElementsByTagName("parsererror"); if (errors.length > 0) { - throw new XMLToJSONError(`XML parsing error: ${errors[0].textContent}`); + throw new XJXError(`XML parsing error: ${errors[0].textContent}`); } return this.nodeToJson(xmlDoc.documentElement); } catch (error) { - throw new XMLToJSONError( + throw new XJXError( `Failed to convert XML to JSON: ${ error instanceof Error ? error.message : String(error) }` diff --git a/src/core/types/errors.ts b/src/core/types/errors.ts index 24bd07e..b977b46 100644 --- a/src/core/types/errors.ts +++ b/src/core/types/errors.ts @@ -5,7 +5,7 @@ /** * Base error class */ -export class XMLToJSONError extends Error { +export class XJXError extends Error { constructor(message: string) { super(message); this.name = 'XMLToJSONError'; @@ -15,7 +15,7 @@ export class XMLToJSONError extends Error { /** * Error for XML parsing issues */ -export class XMLParseError extends XMLToJSONError { +export class XMLParseError extends XJXError { constructor(message: string) { super(`XML parse error: ${message}`); this.name = 'XMLParseError'; @@ -25,7 +25,7 @@ export class XMLParseError extends XMLToJSONError { /** * Error for XML serialization issues */ -export class XMLSerializeError extends XMLToJSONError { +export class XMLSerializeError extends XJXError { constructor(message: string) { super(`XML serialize error: ${message}`); this.name = 'XMLSerializeError'; @@ -35,7 +35,7 @@ export class XMLSerializeError extends XMLToJSONError { /** * Error for environment incompatibility */ -export class EnvironmentError extends XMLToJSONError { +export class EnvironmentError extends XJXError { constructor(message: string) { super(`Environment error: ${message}`); this.name = 'EnvironmentError'; @@ -45,7 +45,7 @@ export class EnvironmentError extends XMLToJSONError { /** * Error for invalid configuration */ -export class ConfigurationError extends XMLToJSONError { +export class ConfigurationError extends XJXError { constructor(message: string) { super(`Configuration error: ${message}`); this.name = 'ConfigurationError'; diff --git a/src/core/utils/XmlUtils.ts b/src/core/utils/XmlUtils.ts index 0a77985..b6b07c5 100644 --- a/src/core/utils/XmlUtils.ts +++ b/src/core/utils/XmlUtils.ts @@ -1,7 +1,7 @@ /** * XMLUtil - Utility functions for XML processing */ -import { XMLToJSONError } from "../types/Errors"; +import { XJXError } from "../types/errors"; import { DOMAdapter } from "../DOMAdapter"; import { Configuration } from "../types/types"; @@ -90,7 +90,7 @@ export class XMLUtil { return serializer(doc).trim(); } catch (error) { - throw new XMLToJSONError( + throw new XJXError( `Failed to pretty print XML: ${ error instanceof Error ? error.message : String(error) }` diff --git a/src/index.ts b/src/index.ts index bd6ddd4..9499331 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,40 +1,16 @@ -/** - * XJX Library - Main entry point - */ -import { XJX } from "./XJX"; -import { XMLToJSON } from "./core/XmlToJsonConverter"; -import { JSONToXML } from "./core/JsonToXmlConverter"; -import { DOMAdapter } from "./core/DOMAdapter"; -import { Configuration } from "./core/types/types"; -import { DEFAULT_CONFIG } from "./core/config/config"; -import { JSONUtil } from "./core/utils/JsonUtils"; -import { XMLUtil } from "./core/utils/XmlUtils"; +// Import locally so you can use it below +import { XJX } from './XJX'; -// Import transformers -import { ValueTransformer } from "./core/transforms/ValueTransformer"; -import { BooleanTransformer } from "./core/transforms/BooleanTransformer"; -import { NumberTransformer } from "./core/transforms/NumberTransformer"; -import { StringReplaceTransformer } from "./core/transforms/StringReplaceTransformer"; +// Core components +export { XJX }; +export { Configuration } from './core/types/types'; +export { DEFAULT_CONFIG } from './core/config/config'; -import * as errors from "./core/types/Errors"; +// Error handling +export { XJXError } from './core/types/errors'; -// Re-export all classes and types (minimal approach) -export { - XJX, - XMLToJSON, - JSONToXML, - DOMAdapter, - Configuration, - DEFAULT_CONFIG, - JSONUtil, - XMLUtil, - errors, - // Export only ValueTransformer and concrete transformers - ValueTransformer, - BooleanTransformer, - NumberTransformer, - StringReplaceTransformer -}; +// Allow custom transformers +export { ValueTransformer } from './core/transforms/ValueTransformer'; -// Default export for easier importing +// Default export export default XJX; \ No newline at end of file From 364e3d588057355125243087227c3a989a13f8bc Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 12:05:33 -0500 Subject: [PATCH 29/38] added jsdom to dev deps --- package-lock.json | 369 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 370 insertions(+) diff --git a/package-lock.json b/package-lock.json index 67550a1..44ef8fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "jest": "^29.6.0", "jest-environment-jsdom": "^29.6.0", "jest-html-reporters": "^3.1.7", + "jsdom": "^26.1.0", "prettier": "^2.8.7", "rimraf": "^4.4.1", "rollup": "^3.29.5", @@ -63,6 +64,27 @@ "node": ">=6.0.0" } }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.4.tgz", + "integrity": "sha512-SeuBV4rnjpFNjI8HSgKUwteuFdkHwkboq31HWzznuqgySQir+jSTczoWVVL4jvOjKjuH80fMDG0Fvg1Sb+OJsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -562,6 +584,121 @@ "dev": true, "license": "MIT" }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.3.tgz", + "integrity": "sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.9.tgz", + "integrity": "sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", @@ -5879,6 +6016,211 @@ "dev": true, "license": "MIT" }, + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/cssstyle": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.1.tgz", + "integrity": "sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.1.2", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -8125,6 +8467,13 @@ "node": ">= 8" } }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -8781,6 +9130,26 @@ "dev": true, "license": "MIT" }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", diff --git a/package.json b/package.json index 7c815d3..201b683 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "jest": "^29.6.0", "jest-environment-jsdom": "^29.6.0", "jest-html-reporters": "^3.1.7", + "jsdom": "^26.1.0", "prettier": "^2.8.7", "rimraf": "^4.4.1", "rollup": "^3.29.5", From 9f810c1d5222904ca0432b6a760586295024c136 Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 13:18:01 -0500 Subject: [PATCH 30/38] json schema generation --- src/core/utils/JsonUtils.ts | 281 +++++++++++++++++++++++++++++++++++- 1 file changed, 280 insertions(+), 1 deletion(-) diff --git a/src/core/utils/JsonUtils.ts b/src/core/utils/JsonUtils.ts index c11a5ea..8ff950d 100644 --- a/src/core/utils/JsonUtils.ts +++ b/src/core/utils/JsonUtils.ts @@ -112,7 +112,7 @@ export class JSONUtil { * @param root Optional root element configuration (either a string or object with $ keys) * @returns XML-like JSON object */ - fromJSONObject(obj: any, root?: any): any { + fromJsonObject(obj: any, root?: any): any { const wrappedObject = this.wrapObject(obj); if (typeof root === "string") { @@ -281,4 +281,283 @@ export class JSONUtil { return target; } + + /** + * Generates a JSON schema that matches the current configuration + * @returns JSON schema object + */ + generateJsonSchema(): Record { + try { + const propNames = this.config.propNames; + const compact = this.config.outputOptions.compact || false; + const preserveNamespaces = this.config.preserveNamespaces; + const preserveComments = this.config.preserveComments; + const preserveCDATA = this.config.preserveCDATA; + const preserveProcessingInstr = this.config.preserveProcessingInstr; + const preserveTextNodes = this.config.preserveTextNodes; + const preserveWhitespace = this.config.preserveWhitespace; + const preserveAttributes = this.config.preserveAttributes; + + // Determine which properties are required based on the configuration + const requiredProps: string[] = []; + + if (!compact) { + // Only add collections as required if they're preserved in the config + if (preserveAttributes) requiredProps.push(propNames.attributes); + + if (preserveCDATA) requiredProps.push(propNames.cdata); + if (preserveComments) requiredProps.push(propNames.comments); + if (preserveProcessingInstr) requiredProps.push(propNames.instruction); + requiredProps.push(propNames.children); + + if (preserveTextNodes) { + requiredProps.push(propNames.value); + + if (preserveNamespaces) { + requiredProps.push(propNames.namespace); + // Note: prefix is not required as it may not be present for all elements + } + } + } + + // Create schema for element properties + const elementProperties: Record = {}; + + // Add namespace property if preserving namespaces + if (preserveNamespaces) { + elementProperties[propNames.namespace] = { + description: "Namespace URI of the element", + type: "string", + }; + + // Add prefix property if preserving namespaces + elementProperties[propNames.prefix] = { + description: "Namespace prefix of the element", + type: "string", + }; + } + + // Add value property if preserving text nodes + if (preserveTextNodes) { + elementProperties[propNames.value] = { + description: "Text content of the element", + type: "string", + }; + } + + // Add attributes property + if (preserveAttributes) { + elementProperties[propNames.attributes] = { + description: "Element attributes", + type: "array", + items: { + type: "object", + patternProperties: { + "^.*$": { + type: "object", + properties: { + [propNames.value]: { + description: "Attribute value", + type: "string", + }, + }, + required: [propNames.value], + }, + }, + additionalProperties: false, + }, + }; + + // If preserving namespaces, add namespace properties to attribute schema + if (preserveNamespaces) { + const attrProps = + elementProperties[propNames.attributes].items.patternProperties[ + "^.*$" + ].properties; + + attrProps[propNames.namespace] = { + description: "Namespace URI of the attribute", + type: "string", + }; + + attrProps[propNames.prefix] = { + description: "Namespace prefix of the attribute", + type: "string", + }; + } + } + + // Add CDATA property if preserving CDATA + if (preserveCDATA) { + elementProperties[propNames.cdata] = { + description: "CDATA section content", + type: "string", + }; + } + + // Add comments property if preserving comments + if (preserveComments) { + elementProperties[propNames.comments] = { + description: "Comment content", + type: "string", + }; + } + + // Add processing instructions property if preserving them + if (preserveProcessingInstr) { + elementProperties[propNames.instruction] = { + description: "Processing instruction", + type: "object", + properties: { + [propNames.target]: { + description: "Processing instruction target", + type: "string", + }, + [propNames.value]: { + description: "Processing instruction content", + type: "string", + }, + }, + required: [propNames.target], + }; + } + + // Add children property with recursive schema + elementProperties[propNames.children] = { + description: "Child elements", + type: "array", + items: { + type: "object", + patternProperties: { + "^.*$": { + $ref: "#/definitions/element", + }, + }, + additionalProperties: false, + }, + }; + + // Create element definition (will be referenced recursively) + const elementDefinition = { + type: "object", + properties: elementProperties, + required: requiredProps, + additionalProperties: false, + }; + + // Build the complete schema + const schema = { + $schema: "https://json-schema.org/draft/2020-12/schema", + title: "XJX JSON Schema", + description: + "Schema for JSON representation of XML documents using the XJX library", + type: "object", + patternProperties: { + "^.*$": { + $ref: "#/definitions/element", + }, + }, + additionalProperties: false, + definitions: { + element: elementDefinition, + }, + }; + + return schema; + } catch (error) { + throw new Error( + `Schema generation failed: ${ + error instanceof Error ? error.message : String(error) + }` + ); + } + } + + /** + * Generate an example JSON object based on the schema + * @param {string} rootName - Name of the root element + * @returns {Record} - Example JSON object + */ + generateExample(rootName: string = "root"): Record { + const propNames = this.config.propNames; + const preserveNamespaces = this.config.preserveNamespaces; + const preserveComments = this.config.preserveComments; + const preserveCDATA = this.config.preserveCDATA; + const preserveProcessingInstr = this.config.preserveProcessingInstr; + const preserveAttributes = this.config.preserveAttributes; + + // Simple example with common features + const example: Record = { + [rootName]: { + [propNames.value]: "Root content", + [propNames.children]: [ + { + child: { + [propNames.value]: "Child content", + }, + }, + ], + }, + }; + + // Add namespace properties if enabled + if (preserveNamespaces) { + example[rootName][propNames.namespace] = "http://example.org/ns"; + example[rootName][propNames.prefix] = "ex"; + example[rootName][propNames.children][0].child[propNames.namespace] = + "http://example.org/ns"; + example[rootName][propNames.children][0].child[propNames.prefix] = "ex"; + } + + // Add attributes if enabled + if (preserveAttributes) { + example[rootName][propNames.attributes] = [ + { id: { [propNames.value]: "root-1" } }, + { lang: { [propNames.value]: "en" } }, + ]; + + if (preserveNamespaces) { + example[rootName][propNames.attributes][1].lang[propNames.prefix] = + "xml"; + } + + example[rootName][propNames.children][0].child[propNames.attributes] = [ + { id: { [propNames.value]: "child-1" } }, + ]; + } + + // Add CDATA if enabled + if (preserveCDATA) { + example[rootName][propNames.children][0].child[propNames.children] = [ + { [propNames.cdata]: "Raw content" }, + ]; + } + + // Add comments if enabled + if (preserveComments) { + if (!example[rootName][propNames.children][0].child[propNames.children]) { + example[rootName][propNames.children][0].child[propNames.children] = []; + } + + example[rootName][propNames.children][0].child[propNames.children].push({ + [propNames.comments]: "Comment about the child", + }); + } + + // Add processing instruction if enabled + if (preserveProcessingInstr) { + if (!example[rootName][propNames.children]) { + example[rootName][propNames.children] = []; + } + + example[rootName][propNames.children].unshift({ + [propNames.instruction]: { + [propNames.target]: "xml-stylesheet", + [propNames.value]: 'type="text/css" href="style.css"', + }, + }); + } + + return example; + } } From a8ca211842f12ef7244fd869e457578fcb711c90 Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 13:21:20 -0500 Subject: [PATCH 31/38] facade methods for schema generation and objectToXJX --- src/XJX.ts | 27 +++++++++++++++++++++++++++ src/core/utils/JsonUtils.ts | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/XJX.ts b/src/XJX.ts index 1afb925..7c38b04 100644 --- a/src/XJX.ts +++ b/src/XJX.ts @@ -94,6 +94,33 @@ export class XJX { return this.xmlUtil.validateXML(xmlString); } + /** + * Generate a JSON schema based on the current configuration + * @returns JSON schema object for validating XML-JSON documents + */ + public generateJsonSchema(): Record { + return this.jsonUtil.generateJsonSchema(); + } + + /** + * Convert a standard JSON object to the XML-like JSON structure + * @param obj Standard JSON object + * @param root Optional root element configuration (string or object with properties) + * @returns XML-like JSON object ready for conversion to XML + */ + public objectToXJX(obj: any, root?: string | Record): Record { + return this.jsonUtil.objectToXJX(obj, root); + } + + /** + * Generate an example JSON object that matches the current configuration + * @param rootName Name of the root element + * @returns Example JSON object + */ + public generateJsonExample(rootName: string = "root"): Record { + return this.jsonUtil.generateExample(rootName); + } + /** * Add a value transformer to the configuration * @param transformer Value transformer to add diff --git a/src/core/utils/JsonUtils.ts b/src/core/utils/JsonUtils.ts index 8ff950d..fbd186c 100644 --- a/src/core/utils/JsonUtils.ts +++ b/src/core/utils/JsonUtils.ts @@ -112,7 +112,7 @@ export class JSONUtil { * @param root Optional root element configuration (either a string or object with $ keys) * @returns XML-like JSON object */ - fromJsonObject(obj: any, root?: any): any { + objectToXJX(obj: any, root?: any): any { const wrappedObject = this.wrapObject(obj); if (typeof root === "string") { From f7d83e3897cf2635ef9330a448482072c357c16d Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 13:44:17 -0500 Subject: [PATCH 32/38] method naming --- README.md | 762 +++++++++++++---------------- dist/dts/XJX.d.ts | 18 + dist/dts/core/types/errors.d.ts | 4 +- dist/dts/core/utils/JsonUtils.d.ts | 13 +- dist/index.d.ts | 18 + dist/index.js | 269 +++++++++- dist/index.js.map | 2 +- dist/stats.html | 2 +- dist/xjx.min.js | 2 +- dist/xjx.min.js.map | 2 +- dist/xjx.umd.js | 269 +++++++++- dist/xjx.umd.js.map | 2 +- package.json | 4 +- src/core/types/errors.ts | 10 +- 14 files changed, 934 insertions(+), 443 deletions(-) diff --git a/README.md b/README.md index c06f1e3..36c7241 100644 --- a/README.md +++ b/README.md @@ -1,353 +1,192 @@ -# XMLToJSON version 1 +# XJX -A simple javascript module for converting XML into JSON within the browser. +A modern ESM library for bidirectional XML to JSON conversion with comprehensive support for namespaces, CDATA sections, comments, processing instructions, and more. -Features -* no external dependencies -* small (~3kb minified) -* simple parsing. pass either a string or xml node and get back a javascipt object ( use JSON.stringify(obj) to get the string representation ) -* supports atrributes, text, cdata, namespaces, default namespaces, attributes with namespaces... you get the idea -* lots of rendering of options -* consistent, predictable output -* browser support - it works on IE 9+, and nearly every version of Chrome, Safari, and Firefox as well as iOS, Android, and Blackberry. (xmlToJSON will work for IE 7/8 as well if you set the xmlns option to false) +[![npm version](https://img.shields.io/npm/v/xjx.svg)](https://www.npmjs.com/package/xjx) +[![Downloads](https://img.shields.io/npm/dm/xjx.svg)](https://www.npmjs.com/package/xjx) +[![License](https://img.shields.io/npm/l/xjx.svg)](https://github.com/yourusername/xjx/blob/main/LICENSE) -Parsing XML (esp. with namespaces) with javascript remains one of the great frustrations of writing web applications. -Most methods are limited by such things as poor browser support, poor or non-existent namespace support, poor attribute handling, incomplete representation, and bloated dependencies. +## Features -xmlToJSON may not solve all of your woes, but it solved some of mine :) +- **Bidirectional Conversion**: Convert XML to JSON and back with high fidelity +- **Complete Node Type Support**: + - Elements with text content + - Attributes + - Namespaces and prefixes + - CDATA sections + - Comments + - Processing instructions +- **Configurable Output**: Customize JSON property names and output options +- **Value Transformers**: Apply type conversions (string → number, boolean, etc.) +- **Path Navigation**: Extract values using simple dot-notation paths +- **Cross-Platform**: Works in both browser and Node.js environments +- **No Dependencies**: Zero production dependencies by default +- **TypeScript**: Full TypeScript support with comprehensive type definitions +- **ESM & UMD**: Modern ESM modules with UMD fallback for wider compatibility -Usage ------ -Include the src -``` - - ``` -and enjoy! xmlToJSON is packaged as a simple module, so use it like this - ```javascript - testString = '
It Works!'; // get some xml (string or document/node) - result = xmlToJSON.parseString(testString); // parse - ``` - The (prettified) result of the above code is - ```javascript -{ - "xml": { - "a": [ - { - "text": "It Works!" - } - ] - } -} -``` +## Installation -Node Usage ----------- -While this library does not officialy support use in the NodeJS environment; several users have reported good results by requiring the xmldom package. +### Browser Installation -User [sethb0](https://github.com/sethb0) has suggested the following workaround example. +You can install XJX via npm and bundle it with your application: +```bash +npm install xjx ``` -const { DOMParser } = require('xmldom'); -const xmlToJSON = require('xmlToJSON'); -xmlToJSON.stringToXML = (string) => new DOMParser().parseFromString(string, 'text/xml'); -``` - -Options -------- -```javascript -// These are the option defaults -var options = { - mergeCDATA: true, // extract cdata and merge with text nodes - grokAttr: true, // convert truthy attributes to boolean, etc - grokText: true, // convert truthy text/attr to boolean, etc - normalize: true, // collapse multiple spaces to single space - xmlns: true, // include namespaces as attributes in output - namespaceKey: '_ns', // tag name for namespace objects - textKey: '_text', // tag name for text nodes - valueKey: '_value', // tag name for attribute values - attrKey: '_attr', // tag for attr groups - cdataKey: '_cdata', // tag for cdata nodes (ignored if mergeCDATA is true) - attrsAsObject: true, // if false, key is used as prefix to name, set prefix to '' to merge children and attrs. - stripAttrPrefix: true, // remove namespace prefixes from attributes - stripElemPrefix: true, // for elements of same name in diff namespaces, you can enable namespaces and access the nskey property - childrenAsArray: true // force children into arrays -}; - -// you can change the defaults by passing the parser an options object of your own -var myOptions = { - mergeCDATA: false, - xmlns: false, - attrsAsObject: false -} +Or use a CDN for direct browser usage: -result = xmlToJSON.parseString(xmlString, myOptions); -``` +```html + + -A more complicated example (with xmlns: true) -```xml - - - - one - ]]>two - three - - + + ``` -results in -```javascript -{ - "xml": [{ - "attr": { - "xmlns": { - "value": "http://default.namespace.uri" - } - }, - "a": [{ - "b": [{ - "attr": { - "id": { - "value": 1 - } - }, - "text": "one" - }, { - "attr": { - "id": { - "value": 2 - } - }, - "text": "some two" - }], - "c": [{ - "attr": { - "xmlns:ns": { - "value": "http://another.namespace" - }, - "id": { - "value": 3 - } - }, - "text": "three" - }] - }] - }] -} -``` +### Node.js Installation (with JSDOM) - -# XMLToJSON version 3 - -A modern ESM library for converting between XML and JSON with support for namespaces, attributes, and various node types. Works in both browser and Node.js environments through a hybrid DOM implementation approach. - -[![npm version](https://img.shields.io/npm/v/xmltojson.svg)](https://www.npmjs.com/package/xmltojson) -[![License](https://img.shields.io/npm/l/xmltojson.svg)](https://github.com/yourusername/xmltojson/blob/main/LICENSE) -[![Build Status](https://img.shields.io/github/workflow/status/yourusername/xmltojson/CI)](https://github.com/yourusername/xmltojson/actions) -[![Coverage Status](https://img.shields.io/codecov/c/github/yourusername/xmltojson)](https://codecov.io/gh/yourusername/xmltojson) - -## Features - -- **Symmetric Conversion**: Transform XML to JSON and back with no data loss -- **Namespace Support**: Preserve namespaces in both XML and JSON -- **Node Type Preservation**: Support for CDATA, comments, processing instructions, and text nodes -- **Highly Configurable**: Customize property names, output format, and preservation options -- **TypeScript Support**: Full TypeScript definitions for better development experience -- **ESM Compatible**: Modern module system for both Node.js and browser environments -- **Hybrid DOM Support**: Flexible DOM implementation with support for browsers, JSDOM, and xmldom - -## Installation +XJX uses DOM APIs and requires a DOM implementation in Node.js environments. By default, it uses JSDOM: ```bash -npm install xmltojson +npm install xjx jsdom ``` -### Node.js Dependencies +JSDOM is a peer dependency that is marked as optional. You'll need to install it separately for Node.js usage. -For Node.js environments, you'll need to install one of these DOM implementations: +### Custom DOM Configuration with Node -```bash -# Option 1: JSDOM (recommended, more complete DOM implementation) -npm install jsdom +If you prefer to use an alternative DOM implementation, you can use `@xmldom/xmldom`: -# Option 2: xmldom (lightweight alternative) -npm install @xmldom/xmldom +```bash +npm install xjx @xmldom/xmldom ``` -## Usage +XJX will automatically detect and use one of these DOM implementations in Node.js environments. -### Basic Usage +## Basic Usage Example + +Converting between XML and JSON is straightforward: ```javascript -import XMLToJSON from 'xmltojson'; +import { XJX } from 'xjx'; -// Create a converter with default settings -const converter = new XMLToJSON(); +// Create an instance of XJX with default configuration +const xjx = new XJX(); -// Convert XML to JSON +// Sample XML string const xmlString = ` - - - Example - This is a with comments - - - - -`; + + + The Great Gatsby + F. Scott Fitzgerald + 1925 + + +`; -const jsonObj = converter.xmlToJson(xmlString); +// Convert XML to JSON +const jsonObj = xjx.xmlToJson(xmlString); console.log(JSON.stringify(jsonObj, null, 2)); -// Convert back to XML -const xmlResult = converter.jsonToXml(jsonObj); -console.log(xmlResult); +// Extract specific values using path navigation +const bookTitle = xjx.getPath(jsonObj, 'library.book.title.$val'); +console.log(`Book title: ${bookTitle}`); // "The Great Gatsby" -// Clean up resources when done (especially important when using JSDOM) -converter.cleanup(); +// Convert JSON back to XML +const newXml = xjx.jsonToXml(jsonObj); +console.log(newXml); + +// Clean up when done (important for Node.js environments) +xjx.cleanup(); ``` -### Custom Configuration +## Configuration Options -```javascript -import XMLToJSON from 'xmltojson'; +XJX is highly configurable. Here's an overview of the available configuration options: -// Create a converter with custom settings -const converter = new XMLToJSON({ +```javascript +const config = { // Features to preserve during transformation - preserveNamespaces: true, - preserveComments: true, - preserveProcessingInstr: true, - preserveCDATA: true, - preserveTextNodes: true, - preserveWhitespace: false, + preserveNamespaces: true, // Preserve namespace information + preserveComments: true, // Preserve XML comments + preserveProcessingInstr: true, // Preserve processing instructions + preserveCDATA: true, // Preserve CDATA sections + preserveTextNodes: true, // Preserve text nodes + preserveWhitespace: false, // Preserve whitespace-only text nodes + preserveAttributes: true, // Preserve element attributes // Output options outputOptions: { - prettyPrint: true, - indent: 3, - compact: true, // removes empty or null nodes and elements - // JSON-specific options - json: { - // Additional JSON options can be added here - }, - // XML-specific options + prettyPrint: true, // Format XML output with indentation + indent: 2, // Indentation spaces for pretty printing + compact: true, // Remove empty/undefined properties + json: {}, // Custom JSON serialization options xml: { - declaration: true, // include the declaration if not present + declaration: true, // Include XML declaration in output }, }, // Property names in the JSON representation propNames: { - namespace: "@ns", - prefix: "@prefix", - attributes: "@attrs", - value: "@val", - cdata: "@cdata", - comments: "@comments", - processing: "@processing", - children: "@children", + namespace: "$ns", // Namespace URI property + prefix: "$pre", // Namespace prefix property + attributes: "$attr", // Attributes collection property + value: "$val", // Text value property + cdata: "$cdata", // CDATA content property + comments: "$cmnt", // Comments property + instruction: "$pi", // Processing instruction property + target: "$trgt", // PI target property + children: "$children", // Child nodes collection property }, -}); - -// Use the converter with custom settings -const jsonObj = converter.xmlToJson(xmlString); -``` - -### Using a Custom DOM Implementation - -The library allows you to provide your own DOM implementation, which is useful for specialized environments or testing: -```javascript -import XMLToJSON from 'xmltojson'; -import { DOMImplementation } from 'xmltojson'; - -// Node.js example with xmldom -const { DOMParser, XMLSerializer, DOMImplementation: XmlDomImpl } = require('@xmldom/xmldom'); - -// Create custom DOM implementation -const domImpl = new XmlDomImpl(); -const customDOM = { - parser: new DOMParser(), - serializer: new XMLSerializer(), - document: domImpl.createDocument(null, null, null), - createDocument: () => domImpl.createDocument(null, null, null) + // Optional value transformers + valueTransforms: [ + // Array of transformer instances (see Value Transformers section) + ] }; -// Create converter with custom DOM implementation -const converter = new XMLToJSON({}, customDOM); - -// Use the converter -const json = converter.xmlToJson(xmlString); - -// Clean up resources when done -converter.cleanup(); +// Create an instance with custom configuration +const xjx = new XJX(config); ``` -### Node.js Usage with JSDOM +You can pass a partial configuration to override just the options you need: ```javascript -import XMLToJSON from 'xmltojson'; -import { JSDOM } from 'jsdom'; +// Override only specific options +const xjx = new XJX({ + preserveWhitespace: true, + outputOptions: { + prettyPrint: false, + } +}); +``` -// Create a converter (will auto-detect JSDOM if installed) -const converter = new XMLToJSON(); +## Namespace Handling -// ... use as normal ... +XJX provides comprehensive support for XML namespaces: -// Clean up resources when done -converter.cleanup(); +```xml + + Content + ``` -## JSON Structure - -The library uses a consistent structure for representing XML in JSON: +The resulting JSON maintains namespace information: -```json +```javascript { - "Root_node": { - "@attrs": [ - { - "attr": { - "@ns": "", - "@prefix": "", - "@val": "" - } - } - ], - "@ns": "", - "@prefix": "", - "@children": [ + "root": { + "$ns": "http://default-ns.com", + "$children": [ { - "node_name": { - "@attrs": [ - { - "attr": { - "@ns": "", - "@prefix": "", - "@val": "" - } - } + "item": { + "$ns": "http://example.org", + "$pre": "ns", + "$attr": [ + { "id": { "$val": "123" } } ], - "@ns": "", - "@children": [ - { - "@processing": { - "target": "target", - "data": "data" - } - }, - { - "@comments": "comment text" - }, - { - "@cdata": "cdata text" - }, - { - "@val": "text content" - } - ] + "$val": "Content" } } ] @@ -355,212 +194,283 @@ The library uses a consistent structure for representing XML in JSON: } ``` -## Browser Support +When converting back to XML, namespace declarations and prefixes are preserved. + +## Value Transformers -This library works in all modern browsers that support the DOM and ES modules. +Value transformers allow automatic conversion between string values in XML and typed values in JSON. For example, you can convert numeric strings to actual numbers or boolean strings to boolean values. -## Node.js Support +### Included Transformers -For Node.js environments, you need to install either: +XJX comes with several built-in transformers: -- `jsdom` (recommended, more complete DOM implementation) -- `@xmldom/xmldom` (lightweight alternative) +#### BooleanTransformer -The library will automatically detect which one is available. +Converts strings like "true" and "false" to actual boolean values. -## API Reference +```javascript +import { XJX, BooleanTransformer } from 'xjx'; -### Class: XMLToJSON +const xjx = new XJX(); +xjx.addTransformer(new BooleanTransformer({ + trueValues: ['true', 'yes', '1'], + falseValues: ['false', 'no', '0'] +})); +``` -The main class for XML to JSON conversion. +#### NumberTransformer -#### Constructor +Converts numeric strings to actual number values. -```typescript -constructor( - config?: Partial, - customDOMImplementation?: DOMImplementation -) +```javascript +import { XJX, NumberTransformer } from 'xjx'; + +const xjx = new XJX(); +xjx.addTransformer(new NumberTransformer({ + parseIntegers: true, + parseFloats: true, + integerFormat: /^-?\d+$/, + floatFormat: /^-?\d*\.\d+$/ +})); ``` -Creates a new converter instance with optional configuration and DOM implementation. +#### StringReplaceTransformer + +Applies regex-based string replacements. + +```javascript +import { XJX, StringReplaceTransformer } from 'xjx'; + +const xjx = new XJX(); +xjx.addTransformer(new StringReplaceTransformer({ + pattern: '/\\s+/g', // Remove whitespace + replacement: '' +})); +``` -#### Methods +### Creating Custom Transformers -##### `xmlToJson(xmlString: string): Record` +You can create custom transformers by extending the `ValueTransformer` base class: + +```javascript +import { XJX, ValueTransformer, TransformContext } from 'xjx'; + +class DateTransformer extends ValueTransformer { + // XML to JSON transformation + protected xmlToJson(value, context) { + if (typeof value !== 'string') return value; + + // Convert ISO date strings to Date objects + if (/^\d{4}-\d{2}-\d{2}$/.test(value)) { + return new Date(value); + } + + return value; + } + + // JSON to XML transformation + protected jsonToXml(value, context) { + if (value instanceof Date) { + // Format date as ISO string + return value.toISOString().split('T')[0]; + } + + return value; + } +} + +const xjx = new XJX(); +xjx.addTransformer(new DateTransformer()); +``` + +## XJX API Reference + +### Constructor + +```javascript +const xjx = new XJX(config); +``` + +Creates a new XJX instance with optional configuration. + +### Core Methods + +#### xmlToJson(xmlString) Converts an XML string to a JSON object. -- **Parameters**: - - `xmlString`: The XML content to convert -- **Returns**: A JSON object representing the XML content +```javascript +const jsonObj = xjx.xmlToJson(xmlString); +``` -##### `jsonToXml(jsonObj: Record): string` +#### jsonToXml(jsonObj) -Converts a JSON object to an XML string. +Converts a JSON object (in XJX format) to an XML string. -- **Parameters**: - - `jsonObj`: The JSON object to convert -- **Returns**: XML string +```javascript +const xmlString = xjx.jsonToXml(jsonObj); +``` -##### `cleanup(): void` +#### getPath(obj, path, fallback) -Cleans up any resources, especially important when using JSDOM. +Retrieves a value from a JSON object using dot notation path. -### Interface: Configuration +```javascript +const value = xjx.getPath(jsonObj, 'root.item.title.$val', 'Default'); +``` -Configuration interface for XMLToJSON. +#### prettyPrintXml(xmlString) -```typescript -interface Configuration { - // Features to preserve during transformation - preserveNamespaces: boolean; - preserveComments: boolean; - preserveProcessingInstr: boolean; - preserveCDATA: boolean; - preserveTextNodes: boolean; - preserveWhitespace: boolean; +Formats an XML string with proper indentation. - // Output options - outputOptions: { - prettyPrint: boolean; - indent: number; - compact: boolean; - json: Record; - xml: { - declaration: boolean; - }; - }; +```javascript +const formattedXml = xjx.prettyPrintXml(xmlString); +``` - // Property names in the JSON representation - propNames: { - namespace: string; - prefix: string; - attributes: string; - value: string; - cdata: string; - comments: string; - processing: string; - children: string; - }; +#### validateXML(xmlString) + +Checks if an XML string is well-formed. + +```javascript +const result = xjx.validateXML(xmlString); +if (result.isValid) { + console.log('XML is valid'); +} else { + console.error(`XML is invalid: ${result.message}`); } ``` -### Class: DOMAdapter +### Transformer Methods -Provides a unified interface for DOM operations across different environments. +#### addTransformer(transformer) -#### Constructor +Adds a value transformer to the configuration. -```typescript -constructor(customImplementation?: DOMImplementation) +```javascript +xjx.addTransformer(new NumberTransformer()); ``` -Creates a new DOMAdapter with an optional custom implementation. +#### clearTransformers() + +Removes all value transformers from the configuration. -### Interface: DOMImplementation +```javascript +xjx.clearTransformers(); +``` -Interface for custom DOM implementations. +### Cleanup -```typescript -interface DOMImplementation { - parser: any; - serializer: any; - document: any; - createDocument: () => Document; -} +#### cleanup() + +Releases any resources, especially important in Node.js environments. + +```javascript +xjx.cleanup(); ``` -## Examples +## Detailed Method Explanations -See the [examples](./examples) directory for detailed usage examples: +### getPath Method -- [Browser Usage](./examples/browser-example.html) -- [Node.js with JSDOM](./examples/node-example.js) -- [Custom DOM Implementation](./examples/custom-dom-example.ts) +The `getPath` method provides a powerful way to extract values from the XML-JSON structure using dot notation. It handles array traversal and special XML structures automatically: -## Configuration Options +```javascript +xjx.getPath(jsonObj, 'path.to.value', defaultValue); +``` -### Preservation Options +Key features: -| Option | Description | Default | -|--------|-------------|---------| -| `preserveNamespaces` | Preserve XML namespaces in JSON | `true` | -| `preserveComments` | Preserve XML comments in JSON | `true` | -| `preserveProcessingInstr` | Preserve XML processing instructions in JSON | `true` | -| `preserveCDATA` | Preserve CDATA sections in JSON | `true` | -| `preserveTextNodes` | Preserve text nodes separately in JSON | `true` | -| `preserveWhitespace` | Preserve whitespace-only text nodes | `false` | +1. **Dot Notation**: Navigate through nested objects using dot notation (e.g., `library.book.title.$val`) +2. **Array Traversal**: Automatically traverses arrays and collects matching values +3. **Index Access**: Access specific array elements with numeric indices (e.g., `library.book.0.title.$val`) +4. **Special XML Properties**: Access XML-specific properties using configured property names (`$val`, `$attr`, etc.) +5. **Default Values**: Specify a fallback value if the path doesn't exist -### Output Options +Examples: -| Option | Description | Default | -|--------|-------------|---------| -| `prettyPrint` | Format XML output with indentation | `true` | -| `indent` | Number of spaces for indentation | `2` | -| `compact` | Remove empty/null properties | `true` | -| `declaration` | Include XML declaration | `true` | +```javascript +// Get a simple text value +const title = xjx.getPath(jsonObj, 'library.book.title.$val'); -### Property Names +// Get an attribute value +const id = xjx.getPath(jsonObj, 'library.book.$attr.0.id.$val'); -| Option | Description | Default | -|--------|-------------|---------| -| `namespace` | Property name for namespace URI | `"@ns"` | -| `prefix` | Property name for namespace prefix | `"@prefix"` | -| `attributes` | Property name for attributes | `"@attrs"` | -| `value` | Property name for text content | `"@val"` | -| `cdata` | Property name for CDATA sections | `"@cdata"` | -| `comments` | Property name for comments | `"@comments"` | -| `processing` | Property name for processing instructions | `"@processing"` | -| `children` | Property name for child nodes | `"@children"` | +// Get values from all books in an array +const authors = xjx.getPath(jsonObj, 'library.book.author.$val'); +// Result: ['F. Scott Fitzgerald', 'Harper Lee', ...] -## Performance Considerations +// Get a specific book by index +const secondBook = xjx.getPath(jsonObj, 'library.book.1'); -- For large XML documents, consider using the lightweight `@xmldom/xmldom` in Node.js -- The `compact` option removes empty properties, reducing JSON size -- Disable unneeded preservation options for better performance +// Provide a default value if path doesn't exist +const publisher = xjx.getPath(jsonObj, 'library.book.publisher.$val', 'Unknown'); +``` -## Troubleshooting +### generateSchema Method -- **DOM implementation not found in Node.js**: Install either `jsdom` or `@xmldom/xmldom` -- **Memory leaks with JSDOM**: Always call `converter.cleanup()` when done -- **XML parsing errors**: Ensure the XML is well-formed +The JSONUtil class includes a `generateJsonSchema` method that creates a JSON Schema for the XJX JSON format based on the current configuration: -## Contributing +```javascript +const jsonUtil = new JSONUtil(config); +const schema = jsonUtil.generateJsonSchema(); +``` -Contributions are welcome! Please feel free to submit a Pull Request. +The generated schema: -1. Fork the repository -2. Create your feature branch (`git checkout -b feature/amazing-feature`) -3. Commit your changes (`git commit -m 'Add some amazing feature'`) -4. Push to the branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request +1. Reflects current configuration settings (property names, preserved features) +2. Includes proper type information for all properties +3. Supports recursive element structures +4. Documents the purpose of each property +5. Can be used for validation with standard JSON Schema validators -## Development +This is useful for: +- Validating XJX JSON structures +- Generating documentation +- Providing hints in IDEs that support JSON Schema +- Data validation in applications -```bash -# Install dependencies -npm install +### jsonToXJX Method -# Build the library -npm run build +The library provides a utility method to convert standard JSON objects to the XJX format: -# Run tests -npm test +```javascript +const jsonUtil = new JSONUtil(config); +const xjxJson = jsonUtil.fromJsonObject(standardJson, rootElementName); +``` -# Run tests with coverage -npm run test:coverage +This transforms a standard JSON object: -# Lint code -npm run lint +```javascript +{ + "name": "John", + "age": 30, + "roles": ["admin", "user"] +} +``` -# Format code -npm run format +Into the XJX format: -# Generate documentation -npm run docs +```javascript +{ + "user": { + "$children": [ + { "name": { "$val": "John" } }, + { "age": { "$val": 30 } }, + { + "roles": { + "$children": [ + { "$val": "admin" }, + { "$val": "user" } + ] + } + } + ] + } +} ``` +This is useful when you want to convert arbitrary JSON data to XML. The second parameter allows you to specify the root element name (in this example, "user"). + ## License -This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details. \ No newline at end of file +MIT \ No newline at end of file diff --git a/dist/dts/XJX.d.ts b/dist/dts/XJX.d.ts index 3d59135..358a6c4 100644 --- a/dist/dts/XJX.d.ts +++ b/dist/dts/XJX.d.ts @@ -46,6 +46,24 @@ export declare class XJX { isValid: boolean; message?: string; }; + /** + * Generate a JSON schema based on the current configuration + * @returns JSON schema object for validating XML-JSON documents + */ + generateJsonSchema(): Record; + /** + * Convert a standard JSON object to the XML-like JSON structure + * @param obj Standard JSON object + * @param root Optional root element configuration (string or object with properties) + * @returns XML-like JSON object ready for conversion to XML + */ + objectToXJX(obj: any, root?: string | Record): Record; + /** + * Generate an example JSON object that matches the current configuration + * @param rootName Name of the root element + * @returns Example JSON object + */ + generateJsonExample(rootName?: string): Record; /** * Add a value transformer to the configuration * @param transformer Value transformer to add diff --git a/dist/dts/core/types/errors.d.ts b/dist/dts/core/types/errors.d.ts index 14ee611..232e907 100644 --- a/dist/dts/core/types/errors.d.ts +++ b/dist/dts/core/types/errors.d.ts @@ -10,13 +10,13 @@ export declare class XJXError extends Error { /** * Error for XML parsing issues */ -export declare class XMLParseError extends XJXError { +export declare class XmlToJsonError extends XJXError { constructor(message: string); } /** * Error for XML serialization issues */ -export declare class XMLSerializeError extends XJXError { +export declare class JsonToXmlError extends XJXError { constructor(message: string); } /** diff --git a/dist/dts/core/utils/JsonUtils.d.ts b/dist/dts/core/utils/JsonUtils.d.ts index e7dfb63..9abb93e 100644 --- a/dist/dts/core/utils/JsonUtils.d.ts +++ b/dist/dts/core/utils/JsonUtils.d.ts @@ -36,7 +36,7 @@ export declare class JSONUtil { * @param root Optional root element configuration (either a string or object with $ keys) * @returns XML-like JSON object */ - fromJSONObject(obj: any, root?: any): any; + objectToXJX(obj: any, root?: any): any; /** * Wraps a standard JSON value in the XML-like JSON structure * @param value Value to wrap @@ -69,4 +69,15 @@ export declare class JSONUtil { * @returns Merged object (target is modified) */ deepMerge(target: T, source: Partial): T; + /** + * Generates a JSON schema that matches the current configuration + * @returns JSON schema object + */ + generateJsonSchema(): Record; + /** + * Generate an example JSON object based on the schema + * @param {string} rootName - Name of the root element + * @returns {Record} - Example JSON object + */ + generateExample(rootName?: string): Record; } diff --git a/dist/index.d.ts b/dist/index.d.ts index e6f73e0..70c539a 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -132,6 +132,24 @@ declare class XJX { isValid: boolean; message?: string; }; + /** + * Generate a JSON schema based on the current configuration + * @returns JSON schema object for validating XML-JSON documents + */ + generateJsonSchema(): Record; + /** + * Convert a standard JSON object to the XML-like JSON structure + * @param obj Standard JSON object + * @param root Optional root element configuration (string or object with properties) + * @returns XML-like JSON object ready for conversion to XML + */ + objectToXJX(obj: any, root?: string | Record): Record; + /** + * Generate an example JSON object that matches the current configuration + * @param rootName Name of the root element + * @returns Example JSON object + */ + generateJsonExample(rootName?: string): Record; /** * Add a value transformer to the configuration * @param transformer Value transformer to add diff --git a/dist/index.js b/dist/index.js index 121cb42..91f0921 100644 --- a/dist/index.js +++ b/dist/index.js @@ -377,7 +377,7 @@ class JSONUtil { * @param root Optional root element configuration (either a string or object with $ keys) * @returns XML-like JSON object */ - fromJSONObject(obj, root) { + objectToXJX(obj, root) { const wrappedObject = this.wrapObject(obj); if (typeof root === "string") { // Root is a simple string: wrap result with this root tag @@ -521,6 +521,249 @@ class JSONUtil { }); return target; } + /** + * Generates a JSON schema that matches the current configuration + * @returns JSON schema object + */ + generateJsonSchema() { + try { + const propNames = this.config.propNames; + const compact = this.config.outputOptions.compact || false; + const preserveNamespaces = this.config.preserveNamespaces; + const preserveComments = this.config.preserveComments; + const preserveCDATA = this.config.preserveCDATA; + const preserveProcessingInstr = this.config.preserveProcessingInstr; + const preserveTextNodes = this.config.preserveTextNodes; + const preserveWhitespace = this.config.preserveWhitespace; + const preserveAttributes = this.config.preserveAttributes; + // Determine which properties are required based on the configuration + const requiredProps = []; + if (!compact) { + // Only add collections as required if they're preserved in the config + if (preserveAttributes) + requiredProps.push(propNames.attributes); + if (preserveCDATA) + requiredProps.push(propNames.cdata); + if (preserveComments) + requiredProps.push(propNames.comments); + if (preserveProcessingInstr) + requiredProps.push(propNames.instruction); + requiredProps.push(propNames.children); + if (preserveTextNodes) { + requiredProps.push(propNames.value); + if (preserveNamespaces) { + requiredProps.push(propNames.namespace); + // Note: prefix is not required as it may not be present for all elements + } + } + } + // Create schema for element properties + const elementProperties = {}; + // Add namespace property if preserving namespaces + if (preserveNamespaces) { + elementProperties[propNames.namespace] = { + description: "Namespace URI of the element", + type: "string", + }; + // Add prefix property if preserving namespaces + elementProperties[propNames.prefix] = { + description: "Namespace prefix of the element", + type: "string", + }; + } + // Add value property if preserving text nodes + if (preserveTextNodes) { + elementProperties[propNames.value] = { + description: "Text content of the element", + type: "string", + }; + } + // Add attributes property + if (preserveAttributes) { + elementProperties[propNames.attributes] = { + description: "Element attributes", + type: "array", + items: { + type: "object", + patternProperties: { + "^.*$": { + type: "object", + properties: { + [propNames.value]: { + description: "Attribute value", + type: "string", + }, + }, + required: [propNames.value], + }, + }, + additionalProperties: false, + }, + }; + // If preserving namespaces, add namespace properties to attribute schema + if (preserveNamespaces) { + const attrProps = elementProperties[propNames.attributes].items.patternProperties["^.*$"].properties; + attrProps[propNames.namespace] = { + description: "Namespace URI of the attribute", + type: "string", + }; + attrProps[propNames.prefix] = { + description: "Namespace prefix of the attribute", + type: "string", + }; + } + } + // Add CDATA property if preserving CDATA + if (preserveCDATA) { + elementProperties[propNames.cdata] = { + description: "CDATA section content", + type: "string", + }; + } + // Add comments property if preserving comments + if (preserveComments) { + elementProperties[propNames.comments] = { + description: "Comment content", + type: "string", + }; + } + // Add processing instructions property if preserving them + if (preserveProcessingInstr) { + elementProperties[propNames.instruction] = { + description: "Processing instruction", + type: "object", + properties: { + [propNames.target]: { + description: "Processing instruction target", + type: "string", + }, + [propNames.value]: { + description: "Processing instruction content", + type: "string", + }, + }, + required: [propNames.target], + }; + } + // Add children property with recursive schema + elementProperties[propNames.children] = { + description: "Child elements", + type: "array", + items: { + type: "object", + patternProperties: { + "^.*$": { + $ref: "#/definitions/element", + }, + }, + additionalProperties: false, + }, + }; + // Create element definition (will be referenced recursively) + const elementDefinition = { + type: "object", + properties: elementProperties, + required: requiredProps, + additionalProperties: false, + }; + // Build the complete schema + const schema = { + $schema: "https://json-schema.org/draft/2020-12/schema", + title: "XJX JSON Schema", + description: "Schema for JSON representation of XML documents using the XJX library", + type: "object", + patternProperties: { + "^.*$": { + $ref: "#/definitions/element", + }, + }, + additionalProperties: false, + definitions: { + element: elementDefinition, + }, + }; + return schema; + } + catch (error) { + throw new Error(`Schema generation failed: ${error instanceof Error ? error.message : String(error)}`); + } + } + /** + * Generate an example JSON object based on the schema + * @param {string} rootName - Name of the root element + * @returns {Record} - Example JSON object + */ + generateExample(rootName = "root") { + const propNames = this.config.propNames; + const preserveNamespaces = this.config.preserveNamespaces; + const preserveComments = this.config.preserveComments; + const preserveCDATA = this.config.preserveCDATA; + const preserveProcessingInstr = this.config.preserveProcessingInstr; + const preserveAttributes = this.config.preserveAttributes; + // Simple example with common features + const example = { + [rootName]: { + [propNames.value]: "Root content", + [propNames.children]: [ + { + child: { + [propNames.value]: "Child content", + }, + }, + ], + }, + }; + // Add namespace properties if enabled + if (preserveNamespaces) { + example[rootName][propNames.namespace] = "http://example.org/ns"; + example[rootName][propNames.prefix] = "ex"; + example[rootName][propNames.children][0].child[propNames.namespace] = + "http://example.org/ns"; + example[rootName][propNames.children][0].child[propNames.prefix] = "ex"; + } + // Add attributes if enabled + if (preserveAttributes) { + example[rootName][propNames.attributes] = [ + { id: { [propNames.value]: "root-1" } }, + { lang: { [propNames.value]: "en" } }, + ]; + if (preserveNamespaces) { + example[rootName][propNames.attributes][1].lang[propNames.prefix] = + "xml"; + } + example[rootName][propNames.children][0].child[propNames.attributes] = [ + { id: { [propNames.value]: "child-1" } }, + ]; + } + // Add CDATA if enabled + if (preserveCDATA) { + example[rootName][propNames.children][0].child[propNames.children] = [ + { [propNames.cdata]: "Raw content" }, + ]; + } + // Add comments if enabled + if (preserveComments) { + if (!example[rootName][propNames.children][0].child[propNames.children]) { + example[rootName][propNames.children][0].child[propNames.children] = []; + } + example[rootName][propNames.children][0].child[propNames.children].push({ + [propNames.comments]: "Comment about the child", + }); + } + // Add processing instruction if enabled + if (preserveProcessingInstr) { + if (!example[rootName][propNames.children]) { + example[rootName][propNames.children] = []; + } + example[rootName][propNames.children].unshift({ + [propNames.instruction]: { + [propNames.target]: "xml-stylesheet", + [propNames.value]: 'type="text/css" href="style.css"', + }, + }); + } + return example; + } } /** @@ -1315,6 +1558,30 @@ class XJX { validateXML(xmlString) { return this.xmlUtil.validateXML(xmlString); } + /** + * Generate a JSON schema based on the current configuration + * @returns JSON schema object for validating XML-JSON documents + */ + generateJsonSchema() { + return this.jsonUtil.generateJsonSchema(); + } + /** + * Convert a standard JSON object to the XML-like JSON structure + * @param obj Standard JSON object + * @param root Optional root element configuration (string or object with properties) + * @returns XML-like JSON object ready for conversion to XML + */ + objectToXJX(obj, root) { + return this.jsonUtil.objectToXJX(obj, root); + } + /** + * Generate an example JSON object that matches the current configuration + * @param rootName Name of the root element + * @returns Example JSON object + */ + generateJsonExample(rootName = "root") { + return this.jsonUtil.generateExample(rootName); + } /** * Add a value transformer to the configuration * @param transformer Value transformer to add diff --git a/dist/index.js.map b/dist/index.js.map index 39c4d5a..1d3e3a5 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../../src/core/types/errors.ts","../../src/core/DOMAdapter.ts","../../src/core/utils/JsonUtils.ts","../../src/core/transforms/TransformUtil.ts","../../src/core/XmlToJsonConverter.ts","../../src/core/utils/XmlUtils.ts","../../src/core/JsonToXmlConverter.ts","../../src/core/config/config.ts","../../src/XJX.ts","../../src/core/transforms/ValueTransformer.ts","../../src/index.ts"],"sourcesContent":["/**\n * Error classes for the XJX library\n */\n\n/**\n * Base error class\n */\nexport class XJXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'XMLToJSONError';\n }\n}\n\n/**\n * Error for XML parsing issues\n */\nexport class XMLParseError extends XJXError {\n constructor(message: string) {\n super(`XML parse error: ${message}`);\n this.name = 'XMLParseError';\n }\n}\n\n/**\n * Error for XML serialization issues\n */\nexport class XMLSerializeError extends XJXError {\n constructor(message: string) {\n super(`XML serialize error: ${message}`);\n this.name = 'XMLSerializeError';\n }\n}\n\n/**\n * Error for environment incompatibility\n */\nexport class EnvironmentError extends XJXError {\n constructor(message: string) {\n super(`Environment error: ${message}`);\n this.name = 'EnvironmentError';\n }\n}\n\n/**\n * Error for invalid configuration\n */\nexport class ConfigurationError extends XJXError {\n constructor(message: string) {\n super(`Configuration error: ${message}`);\n this.name = 'ConfigurationError';\n }\n}","/**\n * DOM Environment provider with unified interface for browser and Node.js\n */\nimport { XJXError } from './types/errors';\n\ninterface NodeTypes {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n}\n\ninterface DOMWindow {\n DOMParser: any;\n XMLSerializer: any;\n Node: {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n };\n document: Document;\n close?: () => void; \n}\n\ninterface JSDOMInstance {\n window: DOMWindow;\n}\n\nexport const DOMAdapter = (() => {\n // Environment-specific DOM implementation\n let domParser: any;\n let xmlSerializer: any;\n let nodeTypes: NodeTypes;\n let docImplementation: any;\n let jsdomInstance: JSDOMInstance | null = null;\n\n try {\n if (typeof window === \"undefined\") {\n // Node.js environment - try JSDOM first\n try {\n const { JSDOM } = require(\"jsdom\");\n jsdomInstance = new JSDOM(\"\", {\n contentType: \"text/xml\",\n }) as JSDOMInstance;\n\n domParser = jsdomInstance.window.DOMParser;\n xmlSerializer = jsdomInstance.window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE,\n TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE,\n CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE,\n COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line\n };\n docImplementation = jsdomInstance.window.document.implementation;\n } catch (jsdomError) {\n // Fall back to xmldom if JSDOM isn't available\n try {\n const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom');\n domParser = DOMParser;\n xmlSerializer = XMLSerializer;\n // Standard DOM node types\n nodeTypes = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n CDATA_SECTION_NODE: 4,\n COMMENT_NODE: 8,\n PROCESSING_INSTRUCTION_NODE: 7,\n DOCUMENT_NODE: 9, \n };\n const implementation = new DOMImplementation();\n docImplementation = implementation;\n } catch (xmldomError) {\n throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`);\n }\n }\n } else {\n // Browser environment\n if (!window.DOMParser) {\n throw new XJXError(\"DOMParser is not available in this environment\");\n }\n\n if (!window.XMLSerializer) {\n throw new XJXError(\"XMLSerializer is not available in this environment\");\n }\n\n domParser = window.DOMParser;\n xmlSerializer = window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: Node.ELEMENT_NODE,\n TEXT_NODE: Node.TEXT_NODE,\n CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE,\n COMMENT_NODE: Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: Node.DOCUMENT_NODE, \n };\n docImplementation = document.implementation;\n }\n } catch (error) {\n throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n return {\n createParser: () => {\n try {\n return new domParser();\n } catch (error) {\n throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createSerializer: () => {\n try {\n return new xmlSerializer();\n } catch (error) {\n throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n nodeTypes,\n \n parseFromString: (xmlString: string, contentType: string = 'text/xml') => {\n try {\n const parser = new domParser();\n return parser.parseFromString(xmlString, contentType);\n } catch (error) {\n throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n serializeToString: (node: Node) => {\n try {\n const serializer = new xmlSerializer();\n return serializer.serializeToString(node);\n } catch (error) {\n throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createDocument: () => {\n try {\n // For browsers, create a document with a root element to avoid issues\n if (typeof window !== \"undefined\") {\n const parser = new domParser();\n return parser.parseFromString('', 'text/xml');\n } else {\n return docImplementation.createDocument(null, null, null);\n }\n } catch (error) {\n throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElement: (tagName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElement(tagName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElement(tagName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElementNS: (namespaceURI: string, qualifiedName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElementNS(namespaceURI, qualifiedName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElementNS(namespaceURI, qualifiedName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createTextNode: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createTextNode(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createTextNode(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createCDATASection: (data: string) => {\n try {\n // For browser compatibility, use document.implementation to create CDATA\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createComment: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createComment(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createComment(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createProcessingInstruction: (target: string, data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n // New helper methods\n \n /**\n * Creates a proper namespace qualified attribute\n */\n setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => {\n try {\n if (namespaceURI) {\n element.setAttributeNS(namespaceURI, qualifiedName, value);\n } else {\n element.setAttribute(qualifiedName, value);\n }\n } catch (error) {\n throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n /**\n * Check if an object is a DOM node\n */\n isNode: (obj: any): boolean => {\n try {\n return obj && typeof obj === 'object' && typeof obj.nodeType === 'number';\n } catch (error) {\n return false;\n }\n },\n \n /**\n * Get DOM node type as string for debugging\n */\n getNodeTypeName: (nodeType: number): string => {\n switch (nodeType) {\n case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE';\n case nodeTypes.TEXT_NODE: return 'TEXT_NODE';\n case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE';\n case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE';\n case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE';\n default: return `UNKNOWN_NODE_TYPE(${nodeType})`;\n }\n },\n \n /**\n * Get all node attributes as an object\n */\n getNodeAttributes: (node: Element): Record => {\n const result: Record = {};\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n result[attr.name] = attr.value;\n }\n return result;\n },\n \n // Cleanup method (mainly for JSDOM)\n cleanup: () => {\n if (jsdomInstance && typeof jsdomInstance.window.close === 'function') {\n jsdomInstance.window.close();\n }\n }\n };\n})();","/**\n * JSONUtil - Utility functions for JSON processing\n */\nimport { Configuration } from \"../types/types\";\n\nexport class JSONUtil {\n private config: Configuration;\n\n /**\n * Constructor for JSONUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * Automatically traverses into children arrays and flattens results.\n *\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns Retrieved value or fallback\n */\n getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n const segments = path.split(\".\");\n let current: any = obj;\n\n for (const segment of segments) {\n if (Array.isArray(current)) {\n // Apply the segment to each array element and flatten results\n const results = current\n .map((item) => this.resolveSegment(item, segment))\n .flat()\n .filter((v) => v !== undefined);\n current = results.length > 0 ? results : undefined;\n } else {\n current = this.resolveSegment(current, segment);\n }\n\n if (current === undefined) return fallback;\n }\n\n // Collapse singleton arrays\n if (Array.isArray(current) && current.length === 1) {\n return current[0];\n }\n\n return current !== undefined ? current : fallback;\n }\n\n /**\n * Resolves a single path segment in the context of a JSON object.\n * Falls back to searching children for matching keys.\n *\n * @param obj The current object\n * @param segment The path segment to resolve\n * @returns Resolved value or undefined\n */\n private resolveSegment(obj: any, segment: string): any {\n if (obj == null || typeof obj !== \"object\") return undefined;\n\n // Direct property access\n if (segment in obj) {\n return obj[segment];\n }\n\n // Check if this is a special property name that matches the config\n if (\n segment === this.config.propNames.value ||\n segment === this.config.propNames.children ||\n segment === this.config.propNames.attributes ||\n segment === this.config.propNames.namespace ||\n segment === this.config.propNames.prefix ||\n segment === this.config.propNames.cdata ||\n segment === this.config.propNames.comments ||\n segment === this.config.propNames.instruction ||\n segment === this.config.propNames.target\n ) {\n const configKey = Object.entries(this.config.propNames).find(\n ([_, value]) => value === segment\n )?.[0];\n\n if (configKey && obj[segment] !== undefined) {\n return obj[segment];\n }\n }\n\n // Check children for objects that contain the segment\n const childrenKey = this.config.propNames.children;\n const children = obj[childrenKey];\n if (Array.isArray(children)) {\n const matches = children\n .map((child) => (segment in child ? child[segment] : undefined))\n .filter((v) => v !== undefined);\n return matches.length > 0 ? matches : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Converts a plain JSON object to the XML-like JSON structure.\n * Optionally wraps the result in a root element with attributes and namespaces.\n *\n * @param obj Standard JSON object\n * @param root Optional root element configuration (either a string or object with $ keys)\n * @returns XML-like JSON object\n */\n fromJSONObject(obj: any, root?: any): any {\n const wrappedObject = this.wrapObject(obj);\n\n if (typeof root === \"string\") {\n // Root is a simple string: wrap result with this root tag\n return { [root]: wrappedObject };\n }\n\n if (root && typeof root === \"object\") {\n // Handle root with config-based keys\n const elementName = root.name || \"root\"; // Default to \"root\" if no name is provided\n const prefix = root[this.config.propNames.prefix] || \"\";\n const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName;\n\n const result: any = {\n [qualifiedName]: {},\n };\n\n // Add attributes to the root element if defined\n const attrsKey = this.config.propNames.attributes;\n if (root[attrsKey] && Array.isArray(root[attrsKey])) {\n result[qualifiedName][attrsKey] = root[attrsKey];\n }\n\n // Merge existing children with the new generated children\n const childrenKey = this.config.propNames.children;\n const children = root[childrenKey] ? root[childrenKey] : [];\n result[qualifiedName][childrenKey] = [\n ...children,\n { [elementName]: wrappedObject },\n ];\n\n // Add namespace and prefix if defined\n const nsKey = this.config.propNames.namespace;\n if (root[nsKey]) {\n result[qualifiedName][nsKey] = root[nsKey];\n }\n\n if (prefix && root[nsKey]) {\n result[qualifiedName][`xmlns:${prefix}`] = root[nsKey];\n }\n\n return result;\n }\n\n // Default behavior if no root is provided\n return wrappedObject;\n }\n\n /**\n * Wraps a standard JSON value in the XML-like JSON structure\n * @param value Value to wrap\n * @returns Wrapped value\n */\n private wrapObject(value: any): any {\n const valKey = this.config.propNames.value;\n const childrenKey = this.config.propNames.children;\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return { [valKey]: value };\n }\n\n if (Array.isArray(value)) {\n // For arrays, wrap each item and return as a children-style array of repeated elements\n return {\n [childrenKey]: value.map((item) => {\n return this.wrapObject(item);\n }),\n };\n }\n\n if (typeof value === \"object\") {\n // It's an object: wrap its properties in children\n const children = Object.entries(value).map(([key, val]) => ({\n [key]: this.wrapObject(val),\n }));\n\n return { [childrenKey]: children };\n }\n\n return undefined; // Fallback for unhandled types\n }\n\n /**\n * Check if an object is empty\n * @param value Value to check\n * @returns true if empty\n */\n isEmpty(value: any): boolean {\n if (value == null) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n }\n\n /**\n * Safely stringify JSON for debugging\n * @param obj Object to stringify\n * @param indent Optional indentation level\n * @returns JSON string representation\n */\n safeStringify(obj: any, indent: number = 2): string {\n try {\n return JSON.stringify(obj, null, indent);\n } catch (error) {\n return \"[Cannot stringify object]\";\n }\n }\n\n /**\n * Deep clone an object\n * @param obj Object to clone\n * @returns Cloned object\n */\n deepClone(obj: any): any {\n try {\n return JSON.parse(JSON.stringify(obj));\n } catch (error) {\n throw new Error(\n `Failed to deep clone object: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Deep merge two objects with proper type handling\n * @param target Target object\n * @param source Source object\n * @returns Merged object (target is modified)\n */\n deepMerge(target: T, source: Partial): T {\n if (!source || typeof source !== \"object\" || source === null) {\n return target;\n }\n\n if (!target || typeof target !== \"object\" || target === null) {\n return source as unknown as T;\n }\n\n Object.keys(source).forEach((key) => {\n const sourceValue = source[key as keyof Partial];\n const targetValue = target[key as keyof T];\n\n // If both source and target values are objects, recursively merge them\n if (\n sourceValue !== null &&\n targetValue !== null &&\n typeof sourceValue === \"object\" &&\n typeof targetValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n !Array.isArray(targetValue)\n ) {\n // Recursively merge the nested objects\n (target as any)[key] = this.deepMerge(targetValue, sourceValue as any);\n } else {\n // Otherwise just replace the value\n (target as any)[key] = sourceValue;\n }\n });\n\n return target;\n }\n}\n","/**\n * Utilities for applying value transformations\n */\nimport { Configuration } from '../types/types';\nimport { TransformContext, TransformDirection } from './ValueTransformer';\nimport { DOMAdapter } from '../DOMAdapter';\n\n/**\n * Utility for applying value transformations\n */\nexport class TransformUtil {\n private config: Configuration;\n\n /**\n * Create a new TransformUtil\n * @param config Configuration\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Apply transforms to a value\n * @param value Value to transform\n * @param context Transformation context\n * @returns Transformed value\n */\n applyTransforms(value: any, context: TransformContext): any {\n // Skip transformation if no transformers are configured\n if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) {\n return value;\n }\n\n // Apply each transformer in sequence\n let transformedValue = value;\n for (const transformer of this.config.valueTransforms) {\n transformedValue = transformer.process(transformedValue, context);\n }\n\n return transformedValue;\n }\n\n /**\n * Create a transform context\n * @param direction Direction of transformation\n * @param nodeName Name of the current node\n * @param nodeType DOM node type\n * @param options Additional context options\n * @returns Transform context\n */\n createContext(\n direction: TransformDirection,\n nodeName: string,\n nodeType: number,\n options: {\n path?: string;\n namespace?: string;\n prefix?: string;\n isAttribute?: boolean;\n attributeName?: string;\n parent?: TransformContext;\n } = {}\n ): TransformContext {\n return {\n direction,\n nodeName,\n nodeType,\n path: options.path || nodeName,\n namespace: options.namespace,\n prefix: options.prefix,\n isAttribute: options.isAttribute || false,\n attributeName: options.attributeName,\n parent: options.parent,\n config: this.config,\n };\n }\n\n /**\n * Get a user-friendly node type name for debugging\n * @param nodeType DOM node type\n * @returns String representation of node type\n */\n getNodeTypeName(nodeType: number): string {\n return DOMAdapter.getNodeTypeName(nodeType);\n }\n}","/**\n * XMLToJSON class for converting XML to JSON with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { JSONUtil } from \"./utils/JsonUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * XMLToJSON Parser for converting XML to JSON\n */\nexport class XMLToJSON {\n private config: Configuration;\n private jsonUtil: JSONUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for XMLToJSON\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.jsonUtil = new JSONUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public parse(xmlString: string): Record {\n try {\n const xmlDoc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n // Check for parsing errors\n const errors = xmlDoc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n throw new XJXError(`XML parsing error: ${errors[0].textContent}`);\n }\n\n return this.nodeToJson(xmlDoc.documentElement);\n } catch (error) {\n throw new XJXError(\n `Failed to convert XML to JSON: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert a DOM node to JSON representation\n * @param node DOM node to convert\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the XML tree\n * @returns JSON representation of the node\n */\n private nodeToJson(node: Node, parentContext?: TransformContext, path: string = \"\"): Record {\n const result: Record = {};\n\n // Handle element nodes\n if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n const element = node as Element;\n // Use localName instead of nodeName to strip namespace prefix\n const nodeName =\n element.localName ||\n element.nodeName.split(\":\").pop() ||\n element.nodeName;\n\n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n const nodeObj: Record = {};\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: currentPath,\n namespace: element.namespaceURI || undefined,\n prefix: element.prefix || undefined,\n parent: parentContext\n }\n );\n\n // Process namespaces if enabled\n if (this.config.preserveNamespaces) {\n const ns = element.namespaceURI;\n if (ns) {\n nodeObj[this.config.propNames.namespace] = ns;\n }\n\n const prefix = element.prefix;\n if (prefix) {\n nodeObj[this.config.propNames.prefix] = prefix;\n }\n }\n\n // Process attributes if enabled\n if (this.config.preserveAttributes && element.attributes.length > 0) {\n const attrs: Array> = [];\n\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n // Strip namespace prefix from attribute name\n const attrLocalName =\n attr.localName || attr.name.split(\":\").pop() || attr.name;\n\n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: `${currentPath}.${attrLocalName}`,\n namespace: attr.namespaceURI || undefined,\n prefix: attr.prefix || undefined,\n isAttribute: true,\n attributeName: attrLocalName,\n parent: context\n }\n );\n\n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attr.value,\n attrContext\n );\n\n // Create attribute object with consistent structure\n const attrObj: Record = {\n [attrLocalName]: {\n [this.config.propNames.value]: transformedValue,\n },\n };\n\n // Add namespace info for attribute if present and enabled\n if (this.config.preserveNamespaces) {\n // Handle attribute namespace\n if (attr.namespaceURI) {\n attrObj[attrLocalName][this.config.propNames.namespace] =\n attr.namespaceURI;\n }\n\n // Handle attribute prefix\n if (attr.prefix) {\n attrObj[attrLocalName][this.config.propNames.prefix] =\n attr.prefix;\n }\n }\n\n attrs.push(attrObj);\n }\n\n if (attrs.length > 0) {\n nodeObj[this.config.propNames.attributes] = attrs;\n }\n }\n\n // Process child nodes\n if (element.childNodes.length > 0) {\n const children: Array> = [];\n const childrenKey = this.config.propNames.children;\n const valueKey = this.config.propNames.value;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n\n // Text nodes - only process if preserveTextNodes is true\n if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) {\n if (this.config.preserveTextNodes) {\n let text = child.nodeValue || \"\";\n\n // Skip whitespace-only text nodes if whitespace preservation is disabled\n if (!this.config.preserveWhitespace) {\n if (text.trim() === \"\") {\n continue;\n }\n // Trim the text when preserveWhitespace is false\n text = text.trim();\n }\n\n // Create text node context\n const textContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#text',\n child.nodeType,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n\n // Apply transformations to text value\n const transformedText = this.transformUtil.applyTransforms(\n text,\n textContext\n );\n\n children.push({ [valueKey]: transformedText });\n }\n }\n // CDATA sections\n else if (\n child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE &&\n this.config.preserveCDATA\n ) {\n // Create CDATA context\n const cdataContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#cdata',\n child.nodeType,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n\n // Apply transformations to CDATA value\n const transformedCData = this.transformUtil.applyTransforms(\n child.nodeValue || \"\",\n cdataContext\n );\n\n children.push({\n [cdataKey]: transformedCData,\n });\n }\n // Comments\n else if (\n child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE &&\n this.config.preserveComments\n ) {\n children.push({\n [commentsKey]: child.nodeValue || \"\",\n });\n }\n // Processing instructions\n else if (\n child.nodeType ===\n DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE &&\n this.config.preserveProcessingInstr\n ) {\n children.push({\n [instructionKey]: {\n [targetKey]: child.nodeName,\n [valueKey]: child.nodeValue || \"\",\n },\n });\n }\n // Element nodes (recursive)\n else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n children.push(this.nodeToJson(child, context, currentPath));\n }\n }\n\n if (children.length > 0) {\n nodeObj[childrenKey] = children;\n }\n }\n\n // Apply compact option - remove empty properties if enabled\n if (this.config.outputOptions.compact) {\n Object.keys(nodeObj).forEach((key) => {\n const cleaned = this.cleanNode(nodeObj[key]);\n if (cleaned === undefined) {\n delete nodeObj[key];\n } else {\n nodeObj[key] = cleaned;\n }\n });\n }\n\n result[nodeName] = nodeObj;\n }\n\n return result;\n }\n\n private cleanNode(node: any): any {\n if (Array.isArray(node)) {\n // Clean each item in the array and filter out empty ones\n const cleanedArray = node\n .map((item) => this.cleanNode(item))\n .filter((item) => {\n return !(\n item === null ||\n item === undefined ||\n (typeof item === \"object\" && Object.keys(item).length === 0)\n );\n });\n return cleanedArray.length > 0 ? cleanedArray : undefined;\n } else if (typeof node === \"object\" && node !== null) {\n // Clean properties recursively\n Object.keys(node).forEach((key) => {\n const cleanedChild = this.cleanNode(node[key]);\n if (\n cleanedChild === null ||\n cleanedChild === undefined ||\n (Array.isArray(cleanedChild) && cleanedChild.length === 0) ||\n (typeof cleanedChild === \"object\" &&\n Object.keys(cleanedChild).length === 0)\n ) {\n delete node[key];\n } else {\n node[key] = cleanedChild;\n }\n });\n\n // Handle the special case for nodes with only empty children/attributes\n const childrenKey = this.config.propNames.children;\n const attrsKey = this.config.propNames.attributes;\n const keys = Object.keys(node);\n if (\n keys.every((key) => key === childrenKey || key === attrsKey) &&\n (node[childrenKey] === undefined ||\n this.jsonUtil.isEmpty(node[childrenKey])) &&\n (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))\n ) {\n return undefined;\n }\n\n return Object.keys(node).length > 0 ? node : undefined;\n }\n\n return node;\n }\n}","/**\n * XMLUtil - Utility functions for XML processing\n */\nimport { XJXError } from \"../types/errors\";\nimport { DOMAdapter } from \"../DOMAdapter\";\nimport { Configuration } from \"../types/types\";\n\nexport class XMLUtil {\n private config: Configuration;\n\n /**\n * Constructor for XMLUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n prettyPrintXml(xmlString: string): string {\n const indent = this.config.outputOptions.indent;\n const INDENT = \" \".repeat(indent);\n\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n const serializer = (node: Node, level = 0): string => {\n const pad = INDENT.repeat(level);\n\n switch (node.nodeType) {\n case DOMAdapter.nodeTypes.ELEMENT_NODE: {\n const el = node as Element;\n const tagName = el.tagName;\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`;\n\n const children = Array.from(el.childNodes);\n\n if (children.length === 0) {\n return `${pad}${openTag.replace(/>$/, \" />\")}\\n`;\n }\n\n // Single text node: print inline\n if (\n children.length === 0 ||\n (children.length === 1 &&\n children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE &&\n children[0].textContent?.trim() === \"\")\n ) {\n // Empty or whitespace-only\n return `${pad}<${tagName}${attrs ? \" \" + attrs : \"\"}>\\n`;\n }\n\n const inner = children\n .map((child) => serializer(child, level + 1))\n .join(\"\");\n return `${pad}${openTag}\\n${inner}${pad}\\n`;\n }\n\n case DOMAdapter.nodeTypes.TEXT_NODE: {\n const text = node.textContent?.trim();\n return text ? `${pad}${text}\\n` : \"\";\n }\n\n case DOMAdapter.nodeTypes.CDATA_SECTION_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.COMMENT_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE:\n const pi = node as ProcessingInstruction;\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.DOCUMENT_NODE:\n return Array.from(node.childNodes)\n .map((child) => serializer(child, level))\n .join(\"\");\n\n default:\n return \"\";\n }\n };\n\n return serializer(doc).trim();\n } catch (error) {\n throw new XJXError(\n `Failed to pretty print XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Check if XML string is well-formed\n * @param xmlString XML string to validate\n * @returns Object with validation result and any error messages\n */\n validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n const errors = doc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n return {\n isValid: false,\n message: errors[0].textContent || \"Unknown parsing error\",\n };\n }\n return { isValid: true };\n } catch (error) {\n return {\n isValid: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Add XML declaration to a string if missing\n * @param xmlString XML string\n * @returns XML string with declaration\n */\n ensureXMLDeclaration(xmlString: string): string {\n if (!xmlString.trim().startsWith(\"\\n' + xmlString;\n }\n return xmlString;\n }\n\n /**\n * Escapes special characters in text for safe XML usage.\n * @param text Text to escape.\n * @returns Escaped XML string.\n */\n escapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&\";\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case '\"':\n return \""\";\n case \"'\":\n return \"'\";\n default:\n return char;\n }\n });\n }\n\n /**\n * Unescapes XML entities back to their character equivalents.\n * @param text Text with XML entities.\n * @returns Unescaped text.\n */\n unescapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => {\n switch (entity) {\n case \"amp\":\n return \"&\";\n case \"lt\":\n return \"<\";\n case \"gt\":\n return \">\";\n case \"quot\":\n return '\"';\n case \"apos\":\n return \"'\";\n default:\n return match;\n }\n });\n }\n\n /**\n * Extract the namespace prefix from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Prefix or null if no prefix\n */\n extractPrefix(qualifiedName: string): string | null {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null;\n }\n\n /**\n * Extract the local name from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Local name\n */\n extractLocalName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0\n ? qualifiedName.substring(colonIndex + 1)\n : qualifiedName;\n }\n\n /**\n * Create a qualified name from prefix and local name\n * @param prefix Namespace prefix (can be null)\n * @param localName Local name\n * @returns Qualified name\n */\n createQualifiedName(prefix: string | null, localName: string): string {\n return prefix ? `${prefix}:${localName}` : localName;\n }\n}","/**\n * JSONToXML class for converting JSON to XML with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { XMLUtil } from \"./utils/XmlUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * JSONToXML for converting JSON to XML\n */\nexport class JSONToXML {\n private config: Configuration;\n private xmlUtil: XMLUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for JSONToXML\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.xmlUtil = new XMLUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert JSON object to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public serialize(jsonObj: Record): string {\n try {\n const doc = DOMAdapter.createDocument();\n const rootElement = this.jsonToNode(jsonObj, doc);\n\n if (rootElement) {\n // Handle the temporary root element if it exists\n if (doc.documentElement && doc.documentElement.nodeName === \"temp\") {\n doc.replaceChild(rootElement, doc.documentElement);\n } else {\n doc.appendChild(rootElement);\n }\n }\n\n // Add XML declaration if specified\n let xmlString = DOMAdapter.serializeToString(doc);\n\n // remove xhtml decl inserted by dom\n xmlString = xmlString.replace(' xmlns=\"http://www.w3.org/1999/xhtml\"', '');\n\n if (this.config.outputOptions.xml.declaration) {\n xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString);\n }\n\n // Apply pretty printing if enabled\n if (this.config.outputOptions.prettyPrint) {\n xmlString = this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n return xmlString;\n } catch (error) {\n throw new XJXError(\n `Failed to convert JSON to XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert JSON object to DOM node\n * @param jsonObj JSON object to convert\n * @param doc Document for creating elements\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the JSON object\n * @returns DOM Element\n */\n private jsonToNode(\n jsonObj: Record,\n doc: Document,\n parentContext?: TransformContext,\n path: string = \"\"\n ): Element | null {\n if (!jsonObj || typeof jsonObj !== \"object\") {\n return null;\n }\n\n // Get the node name (first key in the object)\n const nodeName = Object.keys(jsonObj)[0];\n if (!nodeName) {\n return null;\n }\n\n const nodeData = jsonObj[nodeName];\n \n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n // Create element with namespace if available\n let element: Element;\n const namespaceKey = this.config.propNames.namespace;\n const prefixKey = this.config.propNames.prefix;\n const ns = nodeData[namespaceKey];\n const prefix = nodeData[prefixKey];\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: currentPath,\n namespace: ns,\n prefix: prefix,\n parent: parentContext\n }\n );\n\n if (ns && this.config.preserveNamespaces) {\n if (prefix) {\n // Create element with namespace and prefix\n element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`);\n } else {\n // Create element with namespace but no prefix\n element = DOMAdapter.createElementNS(ns, nodeName);\n }\n } else {\n // Create element without namespace\n element = DOMAdapter.createElement(nodeName);\n }\n\n // Process attributes if enabled\n const attributesKey = this.config.propNames.attributes;\n const valueKey = this.config.propNames.value;\n if (\n this.config.preserveAttributes &&\n nodeData[attributesKey] &&\n Array.isArray(nodeData[attributesKey])\n ) {\n nodeData[attributesKey].forEach(\n (attrObj: Record) => {\n const attrName = Object.keys(attrObj)[0];\n if (!attrName) return;\n\n const attrData = attrObj[attrName];\n \n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: `${currentPath}.${attrName}`,\n namespace: attrData[namespaceKey],\n prefix: attrData[prefixKey],\n isAttribute: true,\n attributeName: attrName,\n parent: context\n }\n );\n \n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attrData[valueKey] || \"\",\n attrContext\n );\n \n const attrNs = attrData[namespaceKey];\n const attrPrefix = attrData[prefixKey];\n\n // Form qualified name for attribute if it has a prefix\n let qualifiedName = attrName;\n if (attrPrefix && this.config.preserveNamespaces) {\n qualifiedName = `${attrPrefix}:${attrName}`;\n }\n\n DOMAdapter.setNamespacedAttribute(\n element, \n (attrNs && this.config.preserveNamespaces) ? attrNs : null, \n qualifiedName, \n transformedValue\n );\n }\n );\n }\n\n // Process simple text value\n if (nodeData[valueKey] !== undefined) {\n // Apply transformations to text value\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n namespace: ns,\n prefix: prefix,\n parent: context\n }\n );\n \n const transformedValue = this.transformUtil.applyTransforms(\n nodeData[valueKey],\n textContext\n );\n \n element.textContent = transformedValue;\n }\n\n // Process children\n const childrenKey = this.config.propNames.children;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n if (\n nodeData[childrenKey] &&\n Array.isArray(nodeData[childrenKey])\n ) {\n nodeData[childrenKey].forEach(\n (child: Record) => {\n // Text nodes\n if (\n child[valueKey] !== undefined &&\n this.config.preserveTextNodes\n ) {\n // Apply transformations to text node\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#text',\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n \n const transformedText = this.transformUtil.applyTransforms(\n child[valueKey],\n textContext\n );\n \n element.appendChild(\n DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))\n );\n }\n // CDATA sections\n else if (\n child[cdataKey] !== undefined &&\n this.config.preserveCDATA\n ) {\n // Apply transformations to CDATA\n const cdataContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#cdata',\n DOMAdapter.nodeTypes.CDATA_SECTION_NODE,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n \n const transformedCData = this.transformUtil.applyTransforms(\n child[cdataKey],\n cdataContext\n );\n \n element.appendChild(\n DOMAdapter.createCDATASection(\n transformedCData\n )\n );\n }\n // Comments\n else if (\n child[commentsKey] !== undefined &&\n this.config.preserveComments\n ) {\n element.appendChild(\n DOMAdapter.createComment(\n child[commentsKey]\n )\n );\n }\n // Processing instructions\n else if (\n child[instructionKey] !== undefined &&\n this.config.preserveProcessingInstr\n ) {\n const piData = child[instructionKey];\n const target = piData[targetKey];\n const data = piData[valueKey] || \"\";\n\n if (target) {\n element.appendChild(\n DOMAdapter.createProcessingInstruction(target, data)\n );\n }\n }\n // Element nodes (recursive)\n else {\n const childElement = this.jsonToNode(child, doc, context, currentPath);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n }\n );\n }\n\n return element;\n }\n}","/**\n * Default configuration for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: Configuration = {\n preserveNamespaces: true,\n preserveComments: true,\n preserveProcessingInstr: true,\n preserveCDATA: true,\n preserveTextNodes: true,\n preserveWhitespace: false,\n preserveAttributes: true,\n\n outputOptions: {\n prettyPrint: true,\n indent: 2,\n compact: true,\n json: {},\n xml: {\n declaration: true,\n },\n },\n\n propNames: {\n namespace: \"$ns\",\n prefix: \"$pre\",\n attributes: \"$attr\",\n value: \"$val\",\n cdata: \"$cdata\",\n comments: \"$cmnt\",\n instruction: \"$pi\", \n target: \"$trgt\", \n children: \"$children\",\n },\n};","/**\n * XJX - Facade class for XML-JSON conversion operations\n */\nimport { XMLToJSON } from \"./core/XmlToJsonConverter\";\nimport { JSONToXML } from \"./core/JsonToXmlConverter\";\nimport { Configuration } from \"./core/types/types\";\nimport { DEFAULT_CONFIG } from \"./core/config/config\";\nimport { DOMAdapter } from \"./core/DOMAdapter\";\nimport { XMLUtil } from \"./core/utils/XmlUtils\";\nimport { JSONUtil } from \"./core/utils/JsonUtils\";\nimport { ValueTransformer } from \"./core/transforms\";\n\nexport class XJX {\n private config: Configuration;\n private xmltojson: XMLToJSON;\n private jsontoxml: JSONToXML;\n private jsonUtil: JSONUtil;\n private xmlUtil: XMLUtil;\n\n /**\n * Constructor for XJX utility\n * @param config Configuration options\n */\n constructor(config: Partial = {}) {\n // First create a jsonUtil instance with default config to use its methods\n this.jsonUtil = new JSONUtil(DEFAULT_CONFIG);\n\n // Create a deep clone of the default config\n const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG);\n\n // Deep merge with the provided config\n this.config = this.jsonUtil.deepMerge(defaultClone, config);\n\n // Re-initialize jsonUtil with the merged config\n this.jsonUtil = new JSONUtil(this.config);\n\n // Initialize other components\n this.xmlUtil = new XMLUtil(this.config);\n this.xmltojson = new XMLToJSON(this.config);\n this.jsontoxml = new JSONToXML(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public xmlToJson(xmlString: string): Record {\n return this.xmltojson.parse(xmlString);\n }\n\n /**\n * Convert JSON object back to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public jsonToXml(jsonObj: Record): string {\n return this.jsontoxml.serialize(jsonObj);\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n public prettyPrintXml(xmlString: string): string {\n return this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns The value at the specified path or the fallback value\n */\n public getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n return this.jsonUtil.getPath(obj, path, fallback);\n }\n\n /**\n * Validate XML string\n * @param xmlString XML string to validate\n * @returns Validation result\n */\n public validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n return this.xmlUtil.validateXML(xmlString);\n }\n\n /**\n * Add a value transformer to the configuration\n * @param transformer Value transformer to add\n * @returns This XJX instance for chaining\n */\n public addTransformer(transformer: ValueTransformer): XJX {\n if (!this.config.valueTransforms) {\n this.config.valueTransforms = [];\n }\n this.config.valueTransforms.push(transformer);\n return this;\n }\n\n /**\n * Removes all value transformers from the configuration\n * @returns This XJX instance for chaining\n */\n public clearTransformers(): XJX {\n this.config.valueTransforms = [];\n return this;\n }\n\n /**\n * Clean up any resources\n */\n public cleanup(): void {\n DOMAdapter.cleanup();\n }\n}","/**\n * Value transformation types and base class for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Direction of the transformation\n */\nexport type TransformDirection = 'xml-to-json' | 'json-to-xml';\n\n/**\n * Context provided to value transformers\n */\nexport interface TransformContext {\n // Core transformation info\n direction: TransformDirection; // Direction of the current transformation\n \n // Node information\n nodeName: string; // Name of the current node\n nodeType: number; // DOM node type (element, text, etc.)\n namespace?: string; // Namespace URI if available\n prefix?: string; // Namespace prefix if available\n \n // Structure information\n path: string; // Dot-notation path to current node\n isAttribute: boolean; // Whether the current value is from an attribute\n attributeName?: string; // Name of attribute if isAttribute is true\n \n // Parent context (creates a chain)\n parent?: TransformContext; // Reference to parent context for traversal\n \n // Configuration reference\n config: Configuration; // Reference to the current configuration\n}\n\n/**\n * Abstract base class for value transformers\n */\nexport abstract class ValueTransformer {\n /**\n * Process a value, transforming it if applicable\n * @param value Value to potentially transform\n * @param context Context including direction and other information\n * @returns Transformed value or original if not applicable\n */\n process(value: any, context: TransformContext): any {\n if (context.direction === 'xml-to-json') {\n return this.xmlToJson(value, context);\n } else {\n return this.jsonToXml(value, context);\n }\n }\n\n /**\n * Transform a value from XML to JSON representation\n * @param value Value from XML\n * @param context Transformation context\n * @returns Transformed value for JSON\n */\n protected xmlToJson(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n\n /**\n * Transform a value from JSON to XML representation\n * @param value Value from JSON\n * @param context Transformation context\n * @returns Transformed value for XML\n */\n protected jsonToXml(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n}","// Import locally so you can use it below\nimport { XJX } from './XJX';\n\n// Core components\nexport { XJX };\nexport { Configuration } from './core/types/types';\nexport { DEFAULT_CONFIG } from './core/config/config';\n\n// Error handling\nexport { XJXError } from './core/types/errors';\n\n// Allow custom transformers\nexport { ValueTransformer } from './core/transforms/ValueTransformer';\n\n// Default export\nexport default XJX;"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["../../src/core/types/errors.ts","../../src/core/DOMAdapter.ts","../../src/core/utils/JsonUtils.ts","../../src/core/transforms/TransformUtil.ts","../../src/core/XmlToJsonConverter.ts","../../src/core/utils/XmlUtils.ts","../../src/core/JsonToXmlConverter.ts","../../src/core/config/config.ts","../../src/XJX.ts","../../src/core/transforms/ValueTransformer.ts","../../src/index.ts"],"sourcesContent":["/**\n * Error classes for the XJX library\n */\n\n/**\n * Base error class\n */\nexport class XJXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'XMLToJSONError';\n }\n}\n\n/**\n * Error for XML parsing issues\n */\nexport class XmlToJsonError extends XJXError {\n constructor(message: string) {\n super(`XML parse error: ${message}`);\n this.name = 'XmlToJsonError';\n }\n}\n\n/**\n * Error for XML serialization issues\n */\nexport class JsonToXmlError extends XJXError {\n constructor(message: string) {\n super(`XML serialization error: ${message}`);\n this.name = 'JsonToXmlError';\n }\n}\n\n/**\n * Error for environment incompatibility\n */\nexport class EnvironmentError extends XJXError {\n constructor(message: string) {\n super(`Environment error: ${message}`);\n this.name = 'EnvironmentError';\n }\n}\n\n/**\n * Error for invalid configuration\n */\nexport class ConfigurationError extends XJXError {\n constructor(message: string) {\n super(`Configuration error: ${message}`);\n this.name = 'ConfigurationError';\n }\n}","/**\n * DOM Environment provider with unified interface for browser and Node.js\n */\nimport { XJXError } from './types/errors';\n\ninterface NodeTypes {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n}\n\ninterface DOMWindow {\n DOMParser: any;\n XMLSerializer: any;\n Node: {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n };\n document: Document;\n close?: () => void; \n}\n\ninterface JSDOMInstance {\n window: DOMWindow;\n}\n\nexport const DOMAdapter = (() => {\n // Environment-specific DOM implementation\n let domParser: any;\n let xmlSerializer: any;\n let nodeTypes: NodeTypes;\n let docImplementation: any;\n let jsdomInstance: JSDOMInstance | null = null;\n\n try {\n if (typeof window === \"undefined\") {\n // Node.js environment - try JSDOM first\n try {\n const { JSDOM } = require(\"jsdom\");\n jsdomInstance = new JSDOM(\"\", {\n contentType: \"text/xml\",\n }) as JSDOMInstance;\n\n domParser = jsdomInstance.window.DOMParser;\n xmlSerializer = jsdomInstance.window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE,\n TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE,\n CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE,\n COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line\n };\n docImplementation = jsdomInstance.window.document.implementation;\n } catch (jsdomError) {\n // Fall back to xmldom if JSDOM isn't available\n try {\n const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom');\n domParser = DOMParser;\n xmlSerializer = XMLSerializer;\n // Standard DOM node types\n nodeTypes = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n CDATA_SECTION_NODE: 4,\n COMMENT_NODE: 8,\n PROCESSING_INSTRUCTION_NODE: 7,\n DOCUMENT_NODE: 9, \n };\n const implementation = new DOMImplementation();\n docImplementation = implementation;\n } catch (xmldomError) {\n throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`);\n }\n }\n } else {\n // Browser environment\n if (!window.DOMParser) {\n throw new XJXError(\"DOMParser is not available in this environment\");\n }\n\n if (!window.XMLSerializer) {\n throw new XJXError(\"XMLSerializer is not available in this environment\");\n }\n\n domParser = window.DOMParser;\n xmlSerializer = window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: Node.ELEMENT_NODE,\n TEXT_NODE: Node.TEXT_NODE,\n CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE,\n COMMENT_NODE: Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: Node.DOCUMENT_NODE, \n };\n docImplementation = document.implementation;\n }\n } catch (error) {\n throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n return {\n createParser: () => {\n try {\n return new domParser();\n } catch (error) {\n throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createSerializer: () => {\n try {\n return new xmlSerializer();\n } catch (error) {\n throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n nodeTypes,\n \n parseFromString: (xmlString: string, contentType: string = 'text/xml') => {\n try {\n const parser = new domParser();\n return parser.parseFromString(xmlString, contentType);\n } catch (error) {\n throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n serializeToString: (node: Node) => {\n try {\n const serializer = new xmlSerializer();\n return serializer.serializeToString(node);\n } catch (error) {\n throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createDocument: () => {\n try {\n // For browsers, create a document with a root element to avoid issues\n if (typeof window !== \"undefined\") {\n const parser = new domParser();\n return parser.parseFromString('', 'text/xml');\n } else {\n return docImplementation.createDocument(null, null, null);\n }\n } catch (error) {\n throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElement: (tagName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElement(tagName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElement(tagName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElementNS: (namespaceURI: string, qualifiedName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElementNS(namespaceURI, qualifiedName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElementNS(namespaceURI, qualifiedName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createTextNode: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createTextNode(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createTextNode(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createCDATASection: (data: string) => {\n try {\n // For browser compatibility, use document.implementation to create CDATA\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createComment: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createComment(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createComment(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createProcessingInstruction: (target: string, data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n // New helper methods\n \n /**\n * Creates a proper namespace qualified attribute\n */\n setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => {\n try {\n if (namespaceURI) {\n element.setAttributeNS(namespaceURI, qualifiedName, value);\n } else {\n element.setAttribute(qualifiedName, value);\n }\n } catch (error) {\n throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n /**\n * Check if an object is a DOM node\n */\n isNode: (obj: any): boolean => {\n try {\n return obj && typeof obj === 'object' && typeof obj.nodeType === 'number';\n } catch (error) {\n return false;\n }\n },\n \n /**\n * Get DOM node type as string for debugging\n */\n getNodeTypeName: (nodeType: number): string => {\n switch (nodeType) {\n case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE';\n case nodeTypes.TEXT_NODE: return 'TEXT_NODE';\n case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE';\n case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE';\n case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE';\n default: return `UNKNOWN_NODE_TYPE(${nodeType})`;\n }\n },\n \n /**\n * Get all node attributes as an object\n */\n getNodeAttributes: (node: Element): Record => {\n const result: Record = {};\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n result[attr.name] = attr.value;\n }\n return result;\n },\n \n // Cleanup method (mainly for JSDOM)\n cleanup: () => {\n if (jsdomInstance && typeof jsdomInstance.window.close === 'function') {\n jsdomInstance.window.close();\n }\n }\n };\n})();","/**\n * JSONUtil - Utility functions for JSON processing\n */\nimport { Configuration } from \"../types/types\";\n\nexport class JSONUtil {\n private config: Configuration;\n\n /**\n * Constructor for JSONUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * Automatically traverses into children arrays and flattens results.\n *\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns Retrieved value or fallback\n */\n getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n const segments = path.split(\".\");\n let current: any = obj;\n\n for (const segment of segments) {\n if (Array.isArray(current)) {\n // Apply the segment to each array element and flatten results\n const results = current\n .map((item) => this.resolveSegment(item, segment))\n .flat()\n .filter((v) => v !== undefined);\n current = results.length > 0 ? results : undefined;\n } else {\n current = this.resolveSegment(current, segment);\n }\n\n if (current === undefined) return fallback;\n }\n\n // Collapse singleton arrays\n if (Array.isArray(current) && current.length === 1) {\n return current[0];\n }\n\n return current !== undefined ? current : fallback;\n }\n\n /**\n * Resolves a single path segment in the context of a JSON object.\n * Falls back to searching children for matching keys.\n *\n * @param obj The current object\n * @param segment The path segment to resolve\n * @returns Resolved value or undefined\n */\n private resolveSegment(obj: any, segment: string): any {\n if (obj == null || typeof obj !== \"object\") return undefined;\n\n // Direct property access\n if (segment in obj) {\n return obj[segment];\n }\n\n // Check if this is a special property name that matches the config\n if (\n segment === this.config.propNames.value ||\n segment === this.config.propNames.children ||\n segment === this.config.propNames.attributes ||\n segment === this.config.propNames.namespace ||\n segment === this.config.propNames.prefix ||\n segment === this.config.propNames.cdata ||\n segment === this.config.propNames.comments ||\n segment === this.config.propNames.instruction ||\n segment === this.config.propNames.target\n ) {\n const configKey = Object.entries(this.config.propNames).find(\n ([_, value]) => value === segment\n )?.[0];\n\n if (configKey && obj[segment] !== undefined) {\n return obj[segment];\n }\n }\n\n // Check children for objects that contain the segment\n const childrenKey = this.config.propNames.children;\n const children = obj[childrenKey];\n if (Array.isArray(children)) {\n const matches = children\n .map((child) => (segment in child ? child[segment] : undefined))\n .filter((v) => v !== undefined);\n return matches.length > 0 ? matches : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Converts a plain JSON object to the XML-like JSON structure.\n * Optionally wraps the result in a root element with attributes and namespaces.\n *\n * @param obj Standard JSON object\n * @param root Optional root element configuration (either a string or object with $ keys)\n * @returns XML-like JSON object\n */\n objectToXJX(obj: any, root?: any): any {\n const wrappedObject = this.wrapObject(obj);\n\n if (typeof root === \"string\") {\n // Root is a simple string: wrap result with this root tag\n return { [root]: wrappedObject };\n }\n\n if (root && typeof root === \"object\") {\n // Handle root with config-based keys\n const elementName = root.name || \"root\"; // Default to \"root\" if no name is provided\n const prefix = root[this.config.propNames.prefix] || \"\";\n const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName;\n\n const result: any = {\n [qualifiedName]: {},\n };\n\n // Add attributes to the root element if defined\n const attrsKey = this.config.propNames.attributes;\n if (root[attrsKey] && Array.isArray(root[attrsKey])) {\n result[qualifiedName][attrsKey] = root[attrsKey];\n }\n\n // Merge existing children with the new generated children\n const childrenKey = this.config.propNames.children;\n const children = root[childrenKey] ? root[childrenKey] : [];\n result[qualifiedName][childrenKey] = [\n ...children,\n { [elementName]: wrappedObject },\n ];\n\n // Add namespace and prefix if defined\n const nsKey = this.config.propNames.namespace;\n if (root[nsKey]) {\n result[qualifiedName][nsKey] = root[nsKey];\n }\n\n if (prefix && root[nsKey]) {\n result[qualifiedName][`xmlns:${prefix}`] = root[nsKey];\n }\n\n return result;\n }\n\n // Default behavior if no root is provided\n return wrappedObject;\n }\n\n /**\n * Wraps a standard JSON value in the XML-like JSON structure\n * @param value Value to wrap\n * @returns Wrapped value\n */\n private wrapObject(value: any): any {\n const valKey = this.config.propNames.value;\n const childrenKey = this.config.propNames.children;\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return { [valKey]: value };\n }\n\n if (Array.isArray(value)) {\n // For arrays, wrap each item and return as a children-style array of repeated elements\n return {\n [childrenKey]: value.map((item) => {\n return this.wrapObject(item);\n }),\n };\n }\n\n if (typeof value === \"object\") {\n // It's an object: wrap its properties in children\n const children = Object.entries(value).map(([key, val]) => ({\n [key]: this.wrapObject(val),\n }));\n\n return { [childrenKey]: children };\n }\n\n return undefined; // Fallback for unhandled types\n }\n\n /**\n * Check if an object is empty\n * @param value Value to check\n * @returns true if empty\n */\n isEmpty(value: any): boolean {\n if (value == null) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n }\n\n /**\n * Safely stringify JSON for debugging\n * @param obj Object to stringify\n * @param indent Optional indentation level\n * @returns JSON string representation\n */\n safeStringify(obj: any, indent: number = 2): string {\n try {\n return JSON.stringify(obj, null, indent);\n } catch (error) {\n return \"[Cannot stringify object]\";\n }\n }\n\n /**\n * Deep clone an object\n * @param obj Object to clone\n * @returns Cloned object\n */\n deepClone(obj: any): any {\n try {\n return JSON.parse(JSON.stringify(obj));\n } catch (error) {\n throw new Error(\n `Failed to deep clone object: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Deep merge two objects with proper type handling\n * @param target Target object\n * @param source Source object\n * @returns Merged object (target is modified)\n */\n deepMerge(target: T, source: Partial): T {\n if (!source || typeof source !== \"object\" || source === null) {\n return target;\n }\n\n if (!target || typeof target !== \"object\" || target === null) {\n return source as unknown as T;\n }\n\n Object.keys(source).forEach((key) => {\n const sourceValue = source[key as keyof Partial];\n const targetValue = target[key as keyof T];\n\n // If both source and target values are objects, recursively merge them\n if (\n sourceValue !== null &&\n targetValue !== null &&\n typeof sourceValue === \"object\" &&\n typeof targetValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n !Array.isArray(targetValue)\n ) {\n // Recursively merge the nested objects\n (target as any)[key] = this.deepMerge(targetValue, sourceValue as any);\n } else {\n // Otherwise just replace the value\n (target as any)[key] = sourceValue;\n }\n });\n\n return target;\n }\n\n /**\n * Generates a JSON schema that matches the current configuration\n * @returns JSON schema object\n */\n generateJsonSchema(): Record {\n try {\n const propNames = this.config.propNames;\n const compact = this.config.outputOptions.compact || false;\n const preserveNamespaces = this.config.preserveNamespaces;\n const preserveComments = this.config.preserveComments;\n const preserveCDATA = this.config.preserveCDATA;\n const preserveProcessingInstr = this.config.preserveProcessingInstr;\n const preserveTextNodes = this.config.preserveTextNodes;\n const preserveWhitespace = this.config.preserveWhitespace;\n const preserveAttributes = this.config.preserveAttributes;\n\n // Determine which properties are required based on the configuration\n const requiredProps: string[] = [];\n\n if (!compact) {\n // Only add collections as required if they're preserved in the config\n if (preserveAttributes) requiredProps.push(propNames.attributes);\n\n if (preserveCDATA) requiredProps.push(propNames.cdata);\n if (preserveComments) requiredProps.push(propNames.comments);\n if (preserveProcessingInstr) requiredProps.push(propNames.instruction);\n requiredProps.push(propNames.children);\n\n if (preserveTextNodes) {\n requiredProps.push(propNames.value);\n\n if (preserveNamespaces) {\n requiredProps.push(propNames.namespace);\n // Note: prefix is not required as it may not be present for all elements\n }\n }\n }\n\n // Create schema for element properties\n const elementProperties: Record = {};\n\n // Add namespace property if preserving namespaces\n if (preserveNamespaces) {\n elementProperties[propNames.namespace] = {\n description: \"Namespace URI of the element\",\n type: \"string\",\n };\n\n // Add prefix property if preserving namespaces\n elementProperties[propNames.prefix] = {\n description: \"Namespace prefix of the element\",\n type: \"string\",\n };\n }\n\n // Add value property if preserving text nodes\n if (preserveTextNodes) {\n elementProperties[propNames.value] = {\n description: \"Text content of the element\",\n type: \"string\",\n };\n }\n\n // Add attributes property\n if (preserveAttributes) {\n elementProperties[propNames.attributes] = {\n description: \"Element attributes\",\n type: \"array\",\n items: {\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n type: \"object\",\n properties: {\n [propNames.value]: {\n description: \"Attribute value\",\n type: \"string\",\n },\n },\n required: [propNames.value],\n },\n },\n additionalProperties: false,\n },\n };\n\n // If preserving namespaces, add namespace properties to attribute schema\n if (preserveNamespaces) {\n const attrProps =\n elementProperties[propNames.attributes].items.patternProperties[\n \"^.*$\"\n ].properties;\n\n attrProps[propNames.namespace] = {\n description: \"Namespace URI of the attribute\",\n type: \"string\",\n };\n\n attrProps[propNames.prefix] = {\n description: \"Namespace prefix of the attribute\",\n type: \"string\",\n };\n }\n }\n\n // Add CDATA property if preserving CDATA\n if (preserveCDATA) {\n elementProperties[propNames.cdata] = {\n description: \"CDATA section content\",\n type: \"string\",\n };\n }\n\n // Add comments property if preserving comments\n if (preserveComments) {\n elementProperties[propNames.comments] = {\n description: \"Comment content\",\n type: \"string\",\n };\n }\n\n // Add processing instructions property if preserving them\n if (preserveProcessingInstr) {\n elementProperties[propNames.instruction] = {\n description: \"Processing instruction\",\n type: \"object\",\n properties: {\n [propNames.target]: {\n description: \"Processing instruction target\",\n type: \"string\",\n },\n [propNames.value]: {\n description: \"Processing instruction content\",\n type: \"string\",\n },\n },\n required: [propNames.target],\n };\n }\n\n // Add children property with recursive schema\n elementProperties[propNames.children] = {\n description: \"Child elements\",\n type: \"array\",\n items: {\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n $ref: \"#/definitions/element\",\n },\n },\n additionalProperties: false,\n },\n };\n\n // Create element definition (will be referenced recursively)\n const elementDefinition = {\n type: \"object\",\n properties: elementProperties,\n required: requiredProps,\n additionalProperties: false,\n };\n\n // Build the complete schema\n const schema = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n title: \"XJX JSON Schema\",\n description:\n \"Schema for JSON representation of XML documents using the XJX library\",\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n $ref: \"#/definitions/element\",\n },\n },\n additionalProperties: false,\n definitions: {\n element: elementDefinition,\n },\n };\n\n return schema;\n } catch (error) {\n throw new Error(\n `Schema generation failed: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Generate an example JSON object based on the schema\n * @param {string} rootName - Name of the root element\n * @returns {Record} - Example JSON object\n */\n generateExample(rootName: string = \"root\"): Record {\n const propNames = this.config.propNames;\n const preserveNamespaces = this.config.preserveNamespaces;\n const preserveComments = this.config.preserveComments;\n const preserveCDATA = this.config.preserveCDATA;\n const preserveProcessingInstr = this.config.preserveProcessingInstr;\n const preserveAttributes = this.config.preserveAttributes;\n\n // Simple example with common features\n const example: Record = {\n [rootName]: {\n [propNames.value]: \"Root content\",\n [propNames.children]: [\n {\n child: {\n [propNames.value]: \"Child content\",\n },\n },\n ],\n },\n };\n\n // Add namespace properties if enabled\n if (preserveNamespaces) {\n example[rootName][propNames.namespace] = \"http://example.org/ns\";\n example[rootName][propNames.prefix] = \"ex\";\n example[rootName][propNames.children][0].child[propNames.namespace] =\n \"http://example.org/ns\";\n example[rootName][propNames.children][0].child[propNames.prefix] = \"ex\";\n }\n\n // Add attributes if enabled\n if (preserveAttributes) {\n example[rootName][propNames.attributes] = [\n { id: { [propNames.value]: \"root-1\" } },\n { lang: { [propNames.value]: \"en\" } },\n ];\n\n if (preserveNamespaces) {\n example[rootName][propNames.attributes][1].lang[propNames.prefix] =\n \"xml\";\n }\n\n example[rootName][propNames.children][0].child[propNames.attributes] = [\n { id: { [propNames.value]: \"child-1\" } },\n ];\n }\n\n // Add CDATA if enabled\n if (preserveCDATA) {\n example[rootName][propNames.children][0].child[propNames.children] = [\n { [propNames.cdata]: \"Raw content\" },\n ];\n }\n\n // Add comments if enabled\n if (preserveComments) {\n if (!example[rootName][propNames.children][0].child[propNames.children]) {\n example[rootName][propNames.children][0].child[propNames.children] = [];\n }\n\n example[rootName][propNames.children][0].child[propNames.children].push({\n [propNames.comments]: \"Comment about the child\",\n });\n }\n\n // Add processing instruction if enabled\n if (preserveProcessingInstr) {\n if (!example[rootName][propNames.children]) {\n example[rootName][propNames.children] = [];\n }\n\n example[rootName][propNames.children].unshift({\n [propNames.instruction]: {\n [propNames.target]: \"xml-stylesheet\",\n [propNames.value]: 'type=\"text/css\" href=\"style.css\"',\n },\n });\n }\n\n return example;\n }\n}\n","/**\n * Utilities for applying value transformations\n */\nimport { Configuration } from '../types/types';\nimport { TransformContext, TransformDirection } from './ValueTransformer';\nimport { DOMAdapter } from '../DOMAdapter';\n\n/**\n * Utility for applying value transformations\n */\nexport class TransformUtil {\n private config: Configuration;\n\n /**\n * Create a new TransformUtil\n * @param config Configuration\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Apply transforms to a value\n * @param value Value to transform\n * @param context Transformation context\n * @returns Transformed value\n */\n applyTransforms(value: any, context: TransformContext): any {\n // Skip transformation if no transformers are configured\n if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) {\n return value;\n }\n\n // Apply each transformer in sequence\n let transformedValue = value;\n for (const transformer of this.config.valueTransforms) {\n transformedValue = transformer.process(transformedValue, context);\n }\n\n return transformedValue;\n }\n\n /**\n * Create a transform context\n * @param direction Direction of transformation\n * @param nodeName Name of the current node\n * @param nodeType DOM node type\n * @param options Additional context options\n * @returns Transform context\n */\n createContext(\n direction: TransformDirection,\n nodeName: string,\n nodeType: number,\n options: {\n path?: string;\n namespace?: string;\n prefix?: string;\n isAttribute?: boolean;\n attributeName?: string;\n parent?: TransformContext;\n } = {}\n ): TransformContext {\n return {\n direction,\n nodeName,\n nodeType,\n path: options.path || nodeName,\n namespace: options.namespace,\n prefix: options.prefix,\n isAttribute: options.isAttribute || false,\n attributeName: options.attributeName,\n parent: options.parent,\n config: this.config,\n };\n }\n\n /**\n * Get a user-friendly node type name for debugging\n * @param nodeType DOM node type\n * @returns String representation of node type\n */\n getNodeTypeName(nodeType: number): string {\n return DOMAdapter.getNodeTypeName(nodeType);\n }\n}","/**\n * XMLToJSON class for converting XML to JSON with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { JSONUtil } from \"./utils/JsonUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * XMLToJSON Parser for converting XML to JSON\n */\nexport class XMLToJSON {\n private config: Configuration;\n private jsonUtil: JSONUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for XMLToJSON\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.jsonUtil = new JSONUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public parse(xmlString: string): Record {\n try {\n const xmlDoc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n // Check for parsing errors\n const errors = xmlDoc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n throw new XJXError(`XML parsing error: ${errors[0].textContent}`);\n }\n\n return this.nodeToJson(xmlDoc.documentElement);\n } catch (error) {\n throw new XJXError(\n `Failed to convert XML to JSON: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert a DOM node to JSON representation\n * @param node DOM node to convert\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the XML tree\n * @returns JSON representation of the node\n */\n private nodeToJson(node: Node, parentContext?: TransformContext, path: string = \"\"): Record {\n const result: Record = {};\n\n // Handle element nodes\n if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n const element = node as Element;\n // Use localName instead of nodeName to strip namespace prefix\n const nodeName =\n element.localName ||\n element.nodeName.split(\":\").pop() ||\n element.nodeName;\n\n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n const nodeObj: Record = {};\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: currentPath,\n namespace: element.namespaceURI || undefined,\n prefix: element.prefix || undefined,\n parent: parentContext\n }\n );\n\n // Process namespaces if enabled\n if (this.config.preserveNamespaces) {\n const ns = element.namespaceURI;\n if (ns) {\n nodeObj[this.config.propNames.namespace] = ns;\n }\n\n const prefix = element.prefix;\n if (prefix) {\n nodeObj[this.config.propNames.prefix] = prefix;\n }\n }\n\n // Process attributes if enabled\n if (this.config.preserveAttributes && element.attributes.length > 0) {\n const attrs: Array> = [];\n\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n // Strip namespace prefix from attribute name\n const attrLocalName =\n attr.localName || attr.name.split(\":\").pop() || attr.name;\n\n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: `${currentPath}.${attrLocalName}`,\n namespace: attr.namespaceURI || undefined,\n prefix: attr.prefix || undefined,\n isAttribute: true,\n attributeName: attrLocalName,\n parent: context\n }\n );\n\n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attr.value,\n attrContext\n );\n\n // Create attribute object with consistent structure\n const attrObj: Record = {\n [attrLocalName]: {\n [this.config.propNames.value]: transformedValue,\n },\n };\n\n // Add namespace info for attribute if present and enabled\n if (this.config.preserveNamespaces) {\n // Handle attribute namespace\n if (attr.namespaceURI) {\n attrObj[attrLocalName][this.config.propNames.namespace] =\n attr.namespaceURI;\n }\n\n // Handle attribute prefix\n if (attr.prefix) {\n attrObj[attrLocalName][this.config.propNames.prefix] =\n attr.prefix;\n }\n }\n\n attrs.push(attrObj);\n }\n\n if (attrs.length > 0) {\n nodeObj[this.config.propNames.attributes] = attrs;\n }\n }\n\n // Process child nodes\n if (element.childNodes.length > 0) {\n const children: Array> = [];\n const childrenKey = this.config.propNames.children;\n const valueKey = this.config.propNames.value;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n\n // Text nodes - only process if preserveTextNodes is true\n if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) {\n if (this.config.preserveTextNodes) {\n let text = child.nodeValue || \"\";\n\n // Skip whitespace-only text nodes if whitespace preservation is disabled\n if (!this.config.preserveWhitespace) {\n if (text.trim() === \"\") {\n continue;\n }\n // Trim the text when preserveWhitespace is false\n text = text.trim();\n }\n\n // Create text node context\n const textContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#text',\n child.nodeType,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n\n // Apply transformations to text value\n const transformedText = this.transformUtil.applyTransforms(\n text,\n textContext\n );\n\n children.push({ [valueKey]: transformedText });\n }\n }\n // CDATA sections\n else if (\n child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE &&\n this.config.preserveCDATA\n ) {\n // Create CDATA context\n const cdataContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#cdata',\n child.nodeType,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n\n // Apply transformations to CDATA value\n const transformedCData = this.transformUtil.applyTransforms(\n child.nodeValue || \"\",\n cdataContext\n );\n\n children.push({\n [cdataKey]: transformedCData,\n });\n }\n // Comments\n else if (\n child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE &&\n this.config.preserveComments\n ) {\n children.push({\n [commentsKey]: child.nodeValue || \"\",\n });\n }\n // Processing instructions\n else if (\n child.nodeType ===\n DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE &&\n this.config.preserveProcessingInstr\n ) {\n children.push({\n [instructionKey]: {\n [targetKey]: child.nodeName,\n [valueKey]: child.nodeValue || \"\",\n },\n });\n }\n // Element nodes (recursive)\n else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n children.push(this.nodeToJson(child, context, currentPath));\n }\n }\n\n if (children.length > 0) {\n nodeObj[childrenKey] = children;\n }\n }\n\n // Apply compact option - remove empty properties if enabled\n if (this.config.outputOptions.compact) {\n Object.keys(nodeObj).forEach((key) => {\n const cleaned = this.cleanNode(nodeObj[key]);\n if (cleaned === undefined) {\n delete nodeObj[key];\n } else {\n nodeObj[key] = cleaned;\n }\n });\n }\n\n result[nodeName] = nodeObj;\n }\n\n return result;\n }\n\n private cleanNode(node: any): any {\n if (Array.isArray(node)) {\n // Clean each item in the array and filter out empty ones\n const cleanedArray = node\n .map((item) => this.cleanNode(item))\n .filter((item) => {\n return !(\n item === null ||\n item === undefined ||\n (typeof item === \"object\" && Object.keys(item).length === 0)\n );\n });\n return cleanedArray.length > 0 ? cleanedArray : undefined;\n } else if (typeof node === \"object\" && node !== null) {\n // Clean properties recursively\n Object.keys(node).forEach((key) => {\n const cleanedChild = this.cleanNode(node[key]);\n if (\n cleanedChild === null ||\n cleanedChild === undefined ||\n (Array.isArray(cleanedChild) && cleanedChild.length === 0) ||\n (typeof cleanedChild === \"object\" &&\n Object.keys(cleanedChild).length === 0)\n ) {\n delete node[key];\n } else {\n node[key] = cleanedChild;\n }\n });\n\n // Handle the special case for nodes with only empty children/attributes\n const childrenKey = this.config.propNames.children;\n const attrsKey = this.config.propNames.attributes;\n const keys = Object.keys(node);\n if (\n keys.every((key) => key === childrenKey || key === attrsKey) &&\n (node[childrenKey] === undefined ||\n this.jsonUtil.isEmpty(node[childrenKey])) &&\n (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))\n ) {\n return undefined;\n }\n\n return Object.keys(node).length > 0 ? node : undefined;\n }\n\n return node;\n }\n}","/**\n * XMLUtil - Utility functions for XML processing\n */\nimport { XJXError } from \"../types/errors\";\nimport { DOMAdapter } from \"../DOMAdapter\";\nimport { Configuration } from \"../types/types\";\n\nexport class XMLUtil {\n private config: Configuration;\n\n /**\n * Constructor for XMLUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n prettyPrintXml(xmlString: string): string {\n const indent = this.config.outputOptions.indent;\n const INDENT = \" \".repeat(indent);\n\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n const serializer = (node: Node, level = 0): string => {\n const pad = INDENT.repeat(level);\n\n switch (node.nodeType) {\n case DOMAdapter.nodeTypes.ELEMENT_NODE: {\n const el = node as Element;\n const tagName = el.tagName;\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`;\n\n const children = Array.from(el.childNodes);\n\n if (children.length === 0) {\n return `${pad}${openTag.replace(/>$/, \" />\")}\\n`;\n }\n\n // Single text node: print inline\n if (\n children.length === 0 ||\n (children.length === 1 &&\n children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE &&\n children[0].textContent?.trim() === \"\")\n ) {\n // Empty or whitespace-only\n return `${pad}<${tagName}${attrs ? \" \" + attrs : \"\"}>\\n`;\n }\n\n const inner = children\n .map((child) => serializer(child, level + 1))\n .join(\"\");\n return `${pad}${openTag}\\n${inner}${pad}\\n`;\n }\n\n case DOMAdapter.nodeTypes.TEXT_NODE: {\n const text = node.textContent?.trim();\n return text ? `${pad}${text}\\n` : \"\";\n }\n\n case DOMAdapter.nodeTypes.CDATA_SECTION_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.COMMENT_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE:\n const pi = node as ProcessingInstruction;\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.DOCUMENT_NODE:\n return Array.from(node.childNodes)\n .map((child) => serializer(child, level))\n .join(\"\");\n\n default:\n return \"\";\n }\n };\n\n return serializer(doc).trim();\n } catch (error) {\n throw new XJXError(\n `Failed to pretty print XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Check if XML string is well-formed\n * @param xmlString XML string to validate\n * @returns Object with validation result and any error messages\n */\n validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n const errors = doc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n return {\n isValid: false,\n message: errors[0].textContent || \"Unknown parsing error\",\n };\n }\n return { isValid: true };\n } catch (error) {\n return {\n isValid: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Add XML declaration to a string if missing\n * @param xmlString XML string\n * @returns XML string with declaration\n */\n ensureXMLDeclaration(xmlString: string): string {\n if (!xmlString.trim().startsWith(\"\\n' + xmlString;\n }\n return xmlString;\n }\n\n /**\n * Escapes special characters in text for safe XML usage.\n * @param text Text to escape.\n * @returns Escaped XML string.\n */\n escapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&\";\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case '\"':\n return \""\";\n case \"'\":\n return \"'\";\n default:\n return char;\n }\n });\n }\n\n /**\n * Unescapes XML entities back to their character equivalents.\n * @param text Text with XML entities.\n * @returns Unescaped text.\n */\n unescapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => {\n switch (entity) {\n case \"amp\":\n return \"&\";\n case \"lt\":\n return \"<\";\n case \"gt\":\n return \">\";\n case \"quot\":\n return '\"';\n case \"apos\":\n return \"'\";\n default:\n return match;\n }\n });\n }\n\n /**\n * Extract the namespace prefix from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Prefix or null if no prefix\n */\n extractPrefix(qualifiedName: string): string | null {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null;\n }\n\n /**\n * Extract the local name from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Local name\n */\n extractLocalName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0\n ? qualifiedName.substring(colonIndex + 1)\n : qualifiedName;\n }\n\n /**\n * Create a qualified name from prefix and local name\n * @param prefix Namespace prefix (can be null)\n * @param localName Local name\n * @returns Qualified name\n */\n createQualifiedName(prefix: string | null, localName: string): string {\n return prefix ? `${prefix}:${localName}` : localName;\n }\n}","/**\n * JSONToXML class for converting JSON to XML with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { XMLUtil } from \"./utils/XmlUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * JSONToXML for converting JSON to XML\n */\nexport class JSONToXML {\n private config: Configuration;\n private xmlUtil: XMLUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for JSONToXML\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.xmlUtil = new XMLUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert JSON object to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public serialize(jsonObj: Record): string {\n try {\n const doc = DOMAdapter.createDocument();\n const rootElement = this.jsonToNode(jsonObj, doc);\n\n if (rootElement) {\n // Handle the temporary root element if it exists\n if (doc.documentElement && doc.documentElement.nodeName === \"temp\") {\n doc.replaceChild(rootElement, doc.documentElement);\n } else {\n doc.appendChild(rootElement);\n }\n }\n\n // Add XML declaration if specified\n let xmlString = DOMAdapter.serializeToString(doc);\n\n // remove xhtml decl inserted by dom\n xmlString = xmlString.replace(' xmlns=\"http://www.w3.org/1999/xhtml\"', '');\n\n if (this.config.outputOptions.xml.declaration) {\n xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString);\n }\n\n // Apply pretty printing if enabled\n if (this.config.outputOptions.prettyPrint) {\n xmlString = this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n return xmlString;\n } catch (error) {\n throw new XJXError(\n `Failed to convert JSON to XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert JSON object to DOM node\n * @param jsonObj JSON object to convert\n * @param doc Document for creating elements\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the JSON object\n * @returns DOM Element\n */\n private jsonToNode(\n jsonObj: Record,\n doc: Document,\n parentContext?: TransformContext,\n path: string = \"\"\n ): Element | null {\n if (!jsonObj || typeof jsonObj !== \"object\") {\n return null;\n }\n\n // Get the node name (first key in the object)\n const nodeName = Object.keys(jsonObj)[0];\n if (!nodeName) {\n return null;\n }\n\n const nodeData = jsonObj[nodeName];\n \n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n // Create element with namespace if available\n let element: Element;\n const namespaceKey = this.config.propNames.namespace;\n const prefixKey = this.config.propNames.prefix;\n const ns = nodeData[namespaceKey];\n const prefix = nodeData[prefixKey];\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: currentPath,\n namespace: ns,\n prefix: prefix,\n parent: parentContext\n }\n );\n\n if (ns && this.config.preserveNamespaces) {\n if (prefix) {\n // Create element with namespace and prefix\n element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`);\n } else {\n // Create element with namespace but no prefix\n element = DOMAdapter.createElementNS(ns, nodeName);\n }\n } else {\n // Create element without namespace\n element = DOMAdapter.createElement(nodeName);\n }\n\n // Process attributes if enabled\n const attributesKey = this.config.propNames.attributes;\n const valueKey = this.config.propNames.value;\n if (\n this.config.preserveAttributes &&\n nodeData[attributesKey] &&\n Array.isArray(nodeData[attributesKey])\n ) {\n nodeData[attributesKey].forEach(\n (attrObj: Record) => {\n const attrName = Object.keys(attrObj)[0];\n if (!attrName) return;\n\n const attrData = attrObj[attrName];\n \n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: `${currentPath}.${attrName}`,\n namespace: attrData[namespaceKey],\n prefix: attrData[prefixKey],\n isAttribute: true,\n attributeName: attrName,\n parent: context\n }\n );\n \n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attrData[valueKey] || \"\",\n attrContext\n );\n \n const attrNs = attrData[namespaceKey];\n const attrPrefix = attrData[prefixKey];\n\n // Form qualified name for attribute if it has a prefix\n let qualifiedName = attrName;\n if (attrPrefix && this.config.preserveNamespaces) {\n qualifiedName = `${attrPrefix}:${attrName}`;\n }\n\n DOMAdapter.setNamespacedAttribute(\n element, \n (attrNs && this.config.preserveNamespaces) ? attrNs : null, \n qualifiedName, \n transformedValue\n );\n }\n );\n }\n\n // Process simple text value\n if (nodeData[valueKey] !== undefined) {\n // Apply transformations to text value\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n namespace: ns,\n prefix: prefix,\n parent: context\n }\n );\n \n const transformedValue = this.transformUtil.applyTransforms(\n nodeData[valueKey],\n textContext\n );\n \n element.textContent = transformedValue;\n }\n\n // Process children\n const childrenKey = this.config.propNames.children;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n if (\n nodeData[childrenKey] &&\n Array.isArray(nodeData[childrenKey])\n ) {\n nodeData[childrenKey].forEach(\n (child: Record) => {\n // Text nodes\n if (\n child[valueKey] !== undefined &&\n this.config.preserveTextNodes\n ) {\n // Apply transformations to text node\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#text',\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n \n const transformedText = this.transformUtil.applyTransforms(\n child[valueKey],\n textContext\n );\n \n element.appendChild(\n DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))\n );\n }\n // CDATA sections\n else if (\n child[cdataKey] !== undefined &&\n this.config.preserveCDATA\n ) {\n // Apply transformations to CDATA\n const cdataContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#cdata',\n DOMAdapter.nodeTypes.CDATA_SECTION_NODE,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n \n const transformedCData = this.transformUtil.applyTransforms(\n child[cdataKey],\n cdataContext\n );\n \n element.appendChild(\n DOMAdapter.createCDATASection(\n transformedCData\n )\n );\n }\n // Comments\n else if (\n child[commentsKey] !== undefined &&\n this.config.preserveComments\n ) {\n element.appendChild(\n DOMAdapter.createComment(\n child[commentsKey]\n )\n );\n }\n // Processing instructions\n else if (\n child[instructionKey] !== undefined &&\n this.config.preserveProcessingInstr\n ) {\n const piData = child[instructionKey];\n const target = piData[targetKey];\n const data = piData[valueKey] || \"\";\n\n if (target) {\n element.appendChild(\n DOMAdapter.createProcessingInstruction(target, data)\n );\n }\n }\n // Element nodes (recursive)\n else {\n const childElement = this.jsonToNode(child, doc, context, currentPath);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n }\n );\n }\n\n return element;\n }\n}","/**\n * Default configuration for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: Configuration = {\n preserveNamespaces: true,\n preserveComments: true,\n preserveProcessingInstr: true,\n preserveCDATA: true,\n preserveTextNodes: true,\n preserveWhitespace: false,\n preserveAttributes: true,\n\n outputOptions: {\n prettyPrint: true,\n indent: 2,\n compact: true,\n json: {},\n xml: {\n declaration: true,\n },\n },\n\n propNames: {\n namespace: \"$ns\",\n prefix: \"$pre\",\n attributes: \"$attr\",\n value: \"$val\",\n cdata: \"$cdata\",\n comments: \"$cmnt\",\n instruction: \"$pi\", \n target: \"$trgt\", \n children: \"$children\",\n },\n};","/**\n * XJX - Facade class for XML-JSON conversion operations\n */\nimport { XMLToJSON } from \"./core/XmlToJsonConverter\";\nimport { JSONToXML } from \"./core/JsonToXmlConverter\";\nimport { Configuration } from \"./core/types/types\";\nimport { DEFAULT_CONFIG } from \"./core/config/config\";\nimport { DOMAdapter } from \"./core/DOMAdapter\";\nimport { XMLUtil } from \"./core/utils/XmlUtils\";\nimport { JSONUtil } from \"./core/utils/JsonUtils\";\nimport { ValueTransformer } from \"./core/transforms\";\n\nexport class XJX {\n private config: Configuration;\n private xmltojson: XMLToJSON;\n private jsontoxml: JSONToXML;\n private jsonUtil: JSONUtil;\n private xmlUtil: XMLUtil;\n\n /**\n * Constructor for XJX utility\n * @param config Configuration options\n */\n constructor(config: Partial = {}) {\n // First create a jsonUtil instance with default config to use its methods\n this.jsonUtil = new JSONUtil(DEFAULT_CONFIG);\n\n // Create a deep clone of the default config\n const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG);\n\n // Deep merge with the provided config\n this.config = this.jsonUtil.deepMerge(defaultClone, config);\n\n // Re-initialize jsonUtil with the merged config\n this.jsonUtil = new JSONUtil(this.config);\n\n // Initialize other components\n this.xmlUtil = new XMLUtil(this.config);\n this.xmltojson = new XMLToJSON(this.config);\n this.jsontoxml = new JSONToXML(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public xmlToJson(xmlString: string): Record {\n return this.xmltojson.parse(xmlString);\n }\n\n /**\n * Convert JSON object back to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public jsonToXml(jsonObj: Record): string {\n return this.jsontoxml.serialize(jsonObj);\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n public prettyPrintXml(xmlString: string): string {\n return this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns The value at the specified path or the fallback value\n */\n public getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n return this.jsonUtil.getPath(obj, path, fallback);\n }\n\n /**\n * Validate XML string\n * @param xmlString XML string to validate\n * @returns Validation result\n */\n public validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n return this.xmlUtil.validateXML(xmlString);\n }\n\n /**\n * Generate a JSON schema based on the current configuration\n * @returns JSON schema object for validating XML-JSON documents\n */\n public generateJsonSchema(): Record {\n return this.jsonUtil.generateJsonSchema();\n }\n\n /**\n * Convert a standard JSON object to the XML-like JSON structure\n * @param obj Standard JSON object\n * @param root Optional root element configuration (string or object with properties)\n * @returns XML-like JSON object ready for conversion to XML\n */\n public objectToXJX(obj: any, root?: string | Record): Record {\n return this.jsonUtil.objectToXJX(obj, root);\n }\n\n /**\n * Generate an example JSON object that matches the current configuration\n * @param rootName Name of the root element\n * @returns Example JSON object\n */\n public generateJsonExample(rootName: string = \"root\"): Record {\n return this.jsonUtil.generateExample(rootName);\n }\n\n /**\n * Add a value transformer to the configuration\n * @param transformer Value transformer to add\n * @returns This XJX instance for chaining\n */\n public addTransformer(transformer: ValueTransformer): XJX {\n if (!this.config.valueTransforms) {\n this.config.valueTransforms = [];\n }\n this.config.valueTransforms.push(transformer);\n return this;\n }\n\n /**\n * Removes all value transformers from the configuration\n * @returns This XJX instance for chaining\n */\n public clearTransformers(): XJX {\n this.config.valueTransforms = [];\n return this;\n }\n\n /**\n * Clean up any resources\n */\n public cleanup(): void {\n DOMAdapter.cleanup();\n }\n}","/**\n * Value transformation types and base class for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Direction of the transformation\n */\nexport type TransformDirection = 'xml-to-json' | 'json-to-xml';\n\n/**\n * Context provided to value transformers\n */\nexport interface TransformContext {\n // Core transformation info\n direction: TransformDirection; // Direction of the current transformation\n \n // Node information\n nodeName: string; // Name of the current node\n nodeType: number; // DOM node type (element, text, etc.)\n namespace?: string; // Namespace URI if available\n prefix?: string; // Namespace prefix if available\n \n // Structure information\n path: string; // Dot-notation path to current node\n isAttribute: boolean; // Whether the current value is from an attribute\n attributeName?: string; // Name of attribute if isAttribute is true\n \n // Parent context (creates a chain)\n parent?: TransformContext; // Reference to parent context for traversal\n \n // Configuration reference\n config: Configuration; // Reference to the current configuration\n}\n\n/**\n * Abstract base class for value transformers\n */\nexport abstract class ValueTransformer {\n /**\n * Process a value, transforming it if applicable\n * @param value Value to potentially transform\n * @param context Context including direction and other information\n * @returns Transformed value or original if not applicable\n */\n process(value: any, context: TransformContext): any {\n if (context.direction === 'xml-to-json') {\n return this.xmlToJson(value, context);\n } else {\n return this.jsonToXml(value, context);\n }\n }\n\n /**\n * Transform a value from XML to JSON representation\n * @param value Value from XML\n * @param context Transformation context\n * @returns Transformed value for JSON\n */\n protected xmlToJson(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n\n /**\n * Transform a value from JSON to XML representation\n * @param value Value from JSON\n * @param context Transformation context\n * @returns Transformed value for XML\n */\n protected jsonToXml(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n}","// Import locally so you can use it below\nimport { XJX } from './XJX';\n\n// Core components\nexport { XJX };\nexport { Configuration } from './core/types/types';\nexport { DEFAULT_CONFIG } from './core/config/config';\n\n// Error handling\nexport { XJXError } from './core/types/errors';\n\n// Allow custom transformers\nexport { ValueTransformer } from './core/transforms/ValueTransformer';\n\n// Default export\nexport default XJX;"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/stats.html b/dist/stats.html index 8277f7f..1e4c7be 100644 --- a/dist/stats.html +++ b/dist/stats.html @@ -4929,7 +4929,7 @@ + + \ No newline at end of file diff --git a/app/package-lock.json b/app/package-lock.json new file mode 100644 index 0000000..277d7b9 --- /dev/null +++ b/app/package-lock.json @@ -0,0 +1,2305 @@ +{ + "name": "xjx-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "xjx-app", + "version": "1.0.0", + "dependencies": { + "@mdi/font": "^7.2.96", + "pinia": "^2.1.6", + "vue": "^3.3.4", + "vuetify": "^3.3.20", + "xjx": "file:../" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.3.4", + "eslint": "^8.49.0", + "eslint-plugin-vue": "^9.17.0", + "vite": "^4.4.9" + } + }, + "..": { + "name": "xjx", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^11.1.6", + "@types/jest": "^29.5.0", + "@types/node": "^18.15.11", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", + "eslint": "^8.37.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "jest": "^29.6.0", + "jest-environment-jsdom": "^29.6.0", + "jest-html-reporters": "^3.1.7", + "jsdom": "^26.1.0", + "prettier": "^2.8.7", + "rimraf": "^4.4.1", + "rollup": "^3.29.5", + "rollup-plugin-dts": "^5.3.1", + "rollup-plugin-filesize": "^10.0.0", + "rollup-plugin-gzip": "^4.0.1", + "rollup-plugin-visualizer": "^5.14.0", + "ts-jest": "^29.1.1", + "typedoc": "^0.24.1", + "typescript": "^5.1.6" + }, + "engines": { + "node": ">=14.16.0" + }, + "peerDependencies": { + "jsdom": "^21.1.1" + }, + "peerDependenciesMeta": { + "@xmldom/xmldom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", + "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@mdi/font": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==", + "license": "Apache-2.0" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", + "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.13", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", + "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", + "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.13", + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.48", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", + "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", + "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", + "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", + "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/runtime-core": "3.5.13", + "@vue/shared": "3.5.13", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", + "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "vue": "3.5.13" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", + "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", + "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/pinia": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz", + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "4.5.13", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.13.tgz", + "integrity": "sha512-Hgp8IF/yZDzKsN1hQWOuQZbrKiaFsbQud+07jJ8h9m9PaHWkpvZ5u55Xw5yYjWRXwRQ4jwFlJvY7T7FUJG9MCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", + "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-sfc": "3.5.13", + "@vue/runtime-dom": "3.5.13", + "@vue/server-renderer": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vuetify": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.8.2.tgz", + "integrity": "sha512-UJNFP4egmKJTQ3V3MKOq+7vIUKO7/Fko5G6yUsOW2Rm0VNBvAjgO6VY6EnK3DTqEKN6ugVXDEPw37NQSTGLZvw==", + "license": "MIT", + "engines": { + "node": "^12.20 || >=14.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=2.1.0", + "vue": "^3.5.0", + "webpack-plugin-vuetify": ">=3.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xjx": { + "resolved": "..", + "link": true + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..53a1841 --- /dev/null +++ b/app/package.json @@ -0,0 +1,24 @@ +{ + "name": "xjx-app", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" + }, + "dependencies": { + "vue": "^3.3.4", + "vuetify": "^3.3.20", + "pinia": "^2.1.6", + "@mdi/font": "^7.2.96", + "xjx": "file:../" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.3.4", + "eslint": "^8.49.0", + "eslint-plugin-vue": "^9.17.0", + "vite": "^4.4.9" + } + } \ No newline at end of file diff --git a/app/src/App.vue b/app/src/App.vue new file mode 100644 index 0000000..da61cc1 --- /dev/null +++ b/app/src/App.vue @@ -0,0 +1,99 @@ + + + \ No newline at end of file diff --git a/app/src/components/ConfigPanel.vue b/app/src/components/ConfigPanel.vue new file mode 100644 index 0000000..c5b98c3 --- /dev/null +++ b/app/src/components/ConfigPanel.vue @@ -0,0 +1,224 @@ + + + \ No newline at end of file diff --git a/app/src/components/JsonEditor.vue b/app/src/components/JsonEditor.vue new file mode 100644 index 0000000..9c2e85d --- /dev/null +++ b/app/src/components/JsonEditor.vue @@ -0,0 +1,125 @@ + + + + + \ No newline at end of file diff --git a/app/src/components/PathNavigator.vue b/app/src/components/PathNavigator.vue new file mode 100644 index 0000000..6c9af76 --- /dev/null +++ b/app/src/components/PathNavigator.vue @@ -0,0 +1,144 @@ + + + \ No newline at end of file diff --git a/app/src/components/XmlEditor.vue b/app/src/components/XmlEditor.vue new file mode 100644 index 0000000..e1dffbd --- /dev/null +++ b/app/src/components/XmlEditor.vue @@ -0,0 +1,116 @@ + + + + + \ No newline at end of file diff --git a/app/src/layouts/MainLayout.vue b/app/src/layouts/MainLayout.vue new file mode 100644 index 0000000..06a2aff --- /dev/null +++ b/app/src/layouts/MainLayout.vue @@ -0,0 +1,62 @@ + + + \ No newline at end of file diff --git a/app/src/main.js b/app/src/main.js new file mode 100644 index 0000000..04d5e8f --- /dev/null +++ b/app/src/main.js @@ -0,0 +1,47 @@ +import { createApp } from 'vue'; +import { createPinia } from 'pinia'; + +// Vuetify +import 'vuetify/styles'; +import { createVuetify } from 'vuetify'; +import * as components from 'vuetify/components'; +import * as directives from 'vuetify/directives'; +import { aliases, mdi } from 'vuetify/iconsets/mdi'; +import '@mdi/font/css/materialdesignicons.css'; + +// App component +import App from './App.vue'; + +// Create Vuetify instance +const vuetify = createVuetify({ + components, + directives, + icons: { + defaultSet: 'mdi', + aliases, + sets: { + mdi, + }, + }, + theme: { + defaultTheme: 'light', + themes: { + light: { + colors: { + primary: '#1867C0', + secondary: '#5CBBF6', + accent: '#005CAF', + }, + }, + }, + }, +}); + +// Create Pinia instance +const pinia = createPinia(); + +// Create and mount the app +const app = createApp(App); +app.use(pinia); +app.use(vuetify); +app.mount('#app'); \ No newline at end of file diff --git a/app/src/services/xjxService.js b/app/src/services/xjxService.js new file mode 100644 index 0000000..10664ba --- /dev/null +++ b/app/src/services/xjxService.js @@ -0,0 +1,129 @@ +/** + * XJX Service + * + * Provides a wrapper around the XJX library for centralized management + * of XML/JSON conversion and other operations. + */ +import { XJX } from 'xjx'; + +export default class XjxService { + /** + * Creates an XJX instance with the provided configuration + * @param {Object} config - XJX configuration options + * @returns {XJX} XJX instance + */ + static createInstance(config) { + return new XJX(config); + } + + /** + * Convert XML string to JSON + * @param {string} xmlString - XML content + * @param {Object} config - XJX configuration options + * @returns {Object} JSON representation of the XML + */ + static xmlToJson(xmlString, config) { + const xjx = this.createInstance(config); + try { + const result = xjx.xmlToJson(xmlString); + return result; + } finally { + xjx.cleanup(); + } + } + + /** + * Convert JSON object to XML string + * @param {Object} jsonObj - JSON content + * @param {Object} config - XJX configuration options + * @returns {string} XML representation of the JSON + */ + static jsonToXml(jsonObj, config) { + const xjx = this.createInstance(config); + try { + const result = xjx.jsonToXml(jsonObj); + return result; + } finally { + xjx.cleanup(); + } + } + + /** + * Pretty print XML string + * @param {string} xmlString - XML content + * @param {Object} config - XJX configuration options + * @returns {string} Formatted XML + */ + static prettyPrintXml(xmlString, config) { + const xjx = this.createInstance(config); + try { + const result = xjx.prettyPrintXml(xmlString); + return result; + } finally { + xjx.cleanup(); + } + } + + /** + * Validate XML string + * @param {string} xmlString - XML content + * @param {Object} config - XJX configuration options + * @returns {Object} Validation result {isValid, message} + */ + static validateXml(xmlString, config) { + const xjx = this.createInstance(config); + try { + const result = xjx.validateXML(xmlString); + return result; + } finally { + xjx.cleanup(); + } + } + + /** + * Get a value from JSON object using a path + * @param {Object} jsonObj - JSON object + * @param {string} path - Dot notation path + * @param {Object} config - XJX configuration options + * @param {any} fallback - Fallback value if path doesn't exist + * @returns {any} Retrieved value + */ + static getPath(jsonObj, path, config, fallback) { + const xjx = this.createInstance(config); + try { + const result = xjx.getPath(jsonObj, path, fallback); + return result; + } finally { + xjx.cleanup(); + } + } + + /** + * Format JSON string with proper indentation + * @param {string} jsonString - JSON string + * @param {number} indent - Indentation spaces + * @returns {string} Formatted JSON string + */ + static formatJson(jsonString, indent = 2) { + try { + const jsonObj = JSON.parse(jsonString); + return JSON.stringify(jsonObj, null, indent); + } catch (error) { + throw new Error(`Failed to format JSON: ${error.message}`); + } + } + + /** + * Validate JSON string + * @param {string} jsonString - JSON string + * @returns {Object} Validation result {isValid, message} + */ + static validateJson(jsonString) { + try { + JSON.parse(jsonString); + return { isValid: true }; + } catch (error) { + return { isValid: false, message: error.message }; + } + } +} \ No newline at end of file diff --git a/app/src/stores/xjxStore.js b/app/src/stores/xjxStore.js new file mode 100644 index 0000000..26138c7 --- /dev/null +++ b/app/src/stores/xjxStore.js @@ -0,0 +1,192 @@ +import { defineStore } from 'pinia'; +import XjxService from '../services/xjxService'; + +// Default XML example +const DEFAULT_XML = ` + + + Example Item + This is a inside]]> with special characters & + + + + + XML + JSON + Converter + + +`; + +// Create and export the store +export const useXjxStore = defineStore('xjx', { + state: () => ({ + // XML and JSON content + xmlContent: DEFAULT_XML, + jsonContent: '', + + // Path navigation + pathInput: '', + pathResult: '', + + // Configuration options + config: { + preserveNamespaces: true, + preserveComments: true, + preserveProcessingInstr: true, + preserveCDATA: true, + preserveTextNodes: true, + preserveAttributes: true, + preserveWhitespace: false, + + outputOptions: { + prettyPrint: true, + indent: 2, + compact: true, + json: {}, + xml: { + declaration: true, + }, + }, + + propNames: { + namespace: "$ns", + prefix: "$pre", + attributes: "$attr", + value: "$val", + cdata: "$cdata", + comments: "$cmnt", + instruction: "$pi", + target: "$trgt", + children: "$children", + }, + }, + + // Utility state + isProcessing: false, + error: null, + + // Notification system + notification: { + show: false, + text: '', + color: 'info', + timeout: 3000 + } + }), + + actions: { + // Convert XML to JSON + async convertXmlToJson() { + this.isProcessing = true; + this.error = null; + + try { + // Use the XjxService to convert XML to JSON + const jsonObj = XjxService.xmlToJson(this.xmlContent, this.config); + + // Format and store the result + this.jsonContent = JSON.stringify(jsonObj, null, 2); + } catch (error) { + this.error = `Error converting XML to JSON: ${error.message}`; + console.error(error); + } finally { + this.isProcessing = false; + } + }, + + // Convert JSON to XML + async convertJsonToXml() { + this.isProcessing = true; + this.error = null; + + try { + // Parse JSON content + const jsonObj = JSON.parse(this.jsonContent); + + // Use the XjxService to convert JSON to XML + const xmlString = XjxService.jsonToXml(jsonObj, this.config); + + // Store the result + this.xmlContent = xmlString; + } catch (error) { + this.error = `Error converting JSON to XML: ${error.message}`; + console.error(error); + } finally { + this.isProcessing = false; + } + }, + + // Reset to defaults + resetToDefault() { + this.xmlContent = DEFAULT_XML; + this.jsonContent = ''; + this.pathInput = ''; + this.pathResult = ''; + this.error = null; + + // Convert the default XML to JSON + this.convertXmlToJson(); + }, + + // Get a value using path + getPath() { + this.error = null; + + try { + if (!this.jsonContent) { + throw new Error('Please convert XML to JSON first before using getPath'); + } + + const jsonObj = JSON.parse(this.jsonContent); + const path = this.pathInput.trim(); + + if (!path) { + throw new Error('Please enter a path to navigate'); + } + + // Use the XjxService to get the path + const result = XjxService.getPath(jsonObj, path, this.config); + + // Format the result for display + if (result === undefined) { + this.pathResult = 'Path not found'; + } else if (typeof result === 'object') { + this.pathResult = JSON.stringify(result, null, 2); + } else { + this.pathResult = String(result); + } + } catch (error) { + this.error = `Error getting path: ${error.message}`; + this.pathResult = ''; + console.error(error); + } + }, + + // Clear path navigation + clearPath() { + this.pathInput = ''; + this.pathResult = ''; + }, + + // Show notification + showNotification(text, color = 'info', timeout = 3000) { + this.notification = { + show: true, + text, + color, + timeout + }; + + // Auto-hide notification after timeout + setTimeout(() => { + this.hideNotification(); + }, timeout); + }, + + // Hide notification + hideNotification() { + this.notification.show = false; + } + } +}); \ No newline at end of file diff --git a/app/vite.config.js b/app/vite.config.js new file mode 100644 index 0000000..92416d9 --- /dev/null +++ b/app/vite.config.js @@ -0,0 +1,21 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import { fileURLToPath, URL } from 'node:url'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + server: { + port: 3000 + }, + build: { + outDir: 'dist', + emptyOutDir: true, + sourcemap: true + } +}); \ No newline at end of file From 2be38015bfc27b7e2b3452b3c81b42e210ca9c61 Mon Sep 17 00:00:00 2001 From: William Summers Date: Fri, 25 Apr 2025 14:17:46 -0500 Subject: [PATCH 34/38] added schemaviewer --- app/src/components/ConfigPanel.vue | 40 ++++++++-- app/src/components/SchemaViewer.vue | 119 ++++++++++++++++++++++++++++ app/src/services/xjxService.js | 15 ++++ 3 files changed, 166 insertions(+), 8 deletions(-) create mode 100644 app/src/components/SchemaViewer.vue diff --git a/app/src/components/ConfigPanel.vue b/app/src/components/ConfigPanel.vue index c5b98c3..ebe9e38 100644 --- a/app/src/components/ConfigPanel.vue +++ b/app/src/components/ConfigPanel.vue @@ -1,6 +1,24 @@ - - \ No newline at end of file + + + + \ No newline at end of file diff --git a/app/src/components/SchemaViewer.vue b/app/src/components/SchemaViewer.vue new file mode 100644 index 0000000..3333f59 --- /dev/null +++ b/app/src/components/SchemaViewer.vue @@ -0,0 +1,119 @@ + + + + + \ No newline at end of file diff --git a/app/src/services/xjxService.js b/app/src/services/xjxService.js index 10664ba..738fba8 100644 --- a/app/src/services/xjxService.js +++ b/app/src/services/xjxService.js @@ -126,4 +126,19 @@ export default class XjxService { return { isValid: false, message: error.message }; } } + + /** + * Generate a JSON schema based on the current configuration + * @param {Object} config - XJX configuration options + * @returns {Object} JSON schema object for validating XML-JSON documents + */ + static generateJsonSchema(config) { + const xjx = this.createInstance(config); + try { + const schema = xjx.generateJsonSchema(); + return schema; + } finally { + xjx.cleanup(); + } + } } \ No newline at end of file From 5647b16282fca2535ac175b8aa7392d4adb80674 Mon Sep 17 00:00:00 2001 From: William Summers Date: Sat, 26 Apr 2025 08:05:17 -0500 Subject: [PATCH 35/38] insane stress document --- testdocs/stress.xml | 246 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 testdocs/stress.xml diff --git a/testdocs/stress.xml b/testdocs/stress.xml new file mode 100644 index 0000000..76a8eea --- /dev/null +++ b/testdocs/stress.xml @@ -0,0 +1,246 @@ + + + + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns="http://example.org/default" + xsi:schemaLocation="http://example.org/test test.xsd" + test:id="root-123" + meta:created="2025-04-25T14:30:00Z" + alt:version="1.0" + status="active"> + + +
+ Testing Multiple Namespaces + This section demonstrates elements from various namespaces + + + String value + 42 + true + + + Section1 namespace element + Metadata namespace element + Using metadata namespace alias + + + Special characters: © copyright, ® registered, € euro, … ellipsis + + + + Composite Element + 42 + +
+ + +
+ Content Models + + + + This uses the overridden metadata namespace + Information in overridden namespace + + + + Testing attribute encoding + + + + + Just a string value + + + + First child + Second child + Third child + + + + This element contains mixed content with both + text and elements intermingled. + + + + + +
+ + +
+ Special XML Features + + + & " ' + It can also contain XML markup like text without being parsed + + ]]> + + + ]]> + + + + + + + +
+ + +
+ Value Types for Transformers + + + true + false + 1 + 0 + yes + no + + + 42 + -273 + 3.14159 + 6.022e23 + 99.44 + 1299.99 + + + 2025-04-25 + 04/25/2025 + 25.04.2025 + + + 2025-04-25T14:30:45Z + Apr 25, 2025 14:30:45 GMT + + + 37.7749,-122.4194 + 37.7749,-122.4194,10.5 + apple,orange,banana,grape + John Doe,"123 Main St, Apt 4B",San Francisco,CA,94105 + 1,2,3,4,5;6,7,8,9,10;11,12,13,14,15 + + + test@example.com + https://example.org/test?param=value + +1-555-123-4567 + 550e8400-e29b-41d4-a716-446655440000 + + + + Please note… this message contains special characters: + Copyright © 2025 + Registered trademark: ® + Euro symbol: € + Em dash: — + Non-breaking space:  between words + Quote marks: “quoted text” + Math symbols: ±5 (plus-minus), ∞ (infinity) + +
+ + +
+ Deeply Nested Structure + + + + + + + Local namespace element + + Deeply nested value + Level 6 with … encoded ellipsis + + + + + + +
+ + +
+ Attributes with Special Values + + +
+ + + +
ID,Name,Department,Salary,HireDate
+ 1001,John Smith,Engineering,85000,2020-05-12 + 1002,Jane Doe,Marketing,75000,2019-11-03 + 1003,Bob Johnson,Finance,95000,2018-02-28 + 1004,Alice Williams,HR,70000,2021-09-15 + 1005,Charlie Brown,Engineering,82000,2020-07-22 +
+ + +
+ Error Handling Tests + + + + Unusual element with many attributes + + + + Element & with " ' characters & markup]]> + + + Element with encoded characters: copyright© registered® euro€ +
+
\ No newline at end of file From 2292ca246f52c66c1252f1113cefc402b3b72abf Mon Sep 17 00:00:00 2001 From: William Summers Date: Sat, 26 Apr 2025 08:19:47 -0500 Subject: [PATCH 36/38] added configuration viewer --- app/src/components/ConfigurationViewer.vue | 152 +++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 app/src/components/ConfigurationViewer.vue diff --git a/app/src/components/ConfigurationViewer.vue b/app/src/components/ConfigurationViewer.vue new file mode 100644 index 0000000..bcbf009 --- /dev/null +++ b/app/src/components/ConfigurationViewer.vue @@ -0,0 +1,152 @@ + + + + + \ No newline at end of file From 45b3a153a64a8bf346711dfb65e32cfdd0e9444d Mon Sep 17 00:00:00 2001 From: William Summers Date: Sat, 26 Apr 2025 08:26:16 -0500 Subject: [PATCH 37/38] fixes for configuration viewer --- app/src/services/xjxService.js | 1 + app/src/stores/xjxStore.js | 104 +++++++++++++++++---------------- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/app/src/services/xjxService.js b/app/src/services/xjxService.js index 738fba8..bea4ce1 100644 --- a/app/src/services/xjxService.js +++ b/app/src/services/xjxService.js @@ -6,6 +6,7 @@ */ import { XJX } from 'xjx'; + export default class XjxService { /** * Creates an XJX instance with the provided configuration diff --git a/app/src/stores/xjxStore.js b/app/src/stores/xjxStore.js index 26138c7..436fe3f 100644 --- a/app/src/stores/xjxStore.js +++ b/app/src/stores/xjxStore.js @@ -1,5 +1,5 @@ -import { defineStore } from 'pinia'; -import XjxService from '../services/xjxService'; +import { defineStore } from "pinia"; +import XjxService from "../services/xjxService"; // Default XML example const DEFAULT_XML = ` @@ -19,16 +19,16 @@ const DEFAULT_XML = ` `; // Create and export the store -export const useXjxStore = defineStore('xjx', { +export const useXjxStore = defineStore("xjx", { state: () => ({ // XML and JSON content xmlContent: DEFAULT_XML, - jsonContent: '', - + jsonContent: "", + // Path navigation - pathInput: '', - pathResult: '', - + pathInput: "", + pathResult: "", + // Configuration options config: { preserveNamespaces: true, @@ -38,7 +38,7 @@ export const useXjxStore = defineStore('xjx', { preserveTextNodes: true, preserveAttributes: true, preserveWhitespace: false, - + outputOptions: { prettyPrint: true, indent: 2, @@ -48,7 +48,7 @@ export const useXjxStore = defineStore('xjx', { declaration: true, }, }, - + propNames: { namespace: "$ns", prefix: "$pre", @@ -60,31 +60,34 @@ export const useXjxStore = defineStore('xjx', { target: "$trgt", children: "$children", }, + + // New: Value transformers array (initialized as an empty array) + valueTransforms: [], }, - + // Utility state isProcessing: false, error: null, - + // Notification system notification: { show: false, - text: '', - color: 'info', - timeout: 3000 - } + text: "", + color: "info", + timeout: 3000, + }, }), - + actions: { // Convert XML to JSON async convertXmlToJson() { this.isProcessing = true; this.error = null; - + try { // Use the XjxService to convert XML to JSON const jsonObj = XjxService.xmlToJson(this.xmlContent, this.config); - + // Format and store the result this.jsonContent = JSON.stringify(jsonObj, null, 2); } catch (error) { @@ -94,19 +97,19 @@ export const useXjxStore = defineStore('xjx', { this.isProcessing = false; } }, - + // Convert JSON to XML async convertJsonToXml() { this.isProcessing = true; this.error = null; - + try { // Parse JSON content const jsonObj = JSON.parse(this.jsonContent); - + // Use the XjxService to convert JSON to XML const xmlString = XjxService.jsonToXml(jsonObj, this.config); - + // Store the result this.xmlContent = xmlString; } catch (error) { @@ -116,77 +119,80 @@ export const useXjxStore = defineStore('xjx', { this.isProcessing = false; } }, - + // Reset to defaults resetToDefault() { this.xmlContent = DEFAULT_XML; - this.jsonContent = ''; - this.pathInput = ''; - this.pathResult = ''; + this.jsonContent = ""; + this.pathInput = ""; + this.pathResult = ""; this.error = null; - + this.config.valueTransforms = []; // Reset transformers + // Convert the default XML to JSON this.convertXmlToJson(); }, - + // Get a value using path getPath() { this.error = null; - + try { if (!this.jsonContent) { - throw new Error('Please convert XML to JSON first before using getPath'); + throw new Error( + "Please convert XML to JSON first before using getPath" + ); } - + const jsonObj = JSON.parse(this.jsonContent); const path = this.pathInput.trim(); - + if (!path) { - throw new Error('Please enter a path to navigate'); + throw new Error("Please enter a path to navigate"); } - + // Use the XjxService to get the path const result = XjxService.getPath(jsonObj, path, this.config); - + // Format the result for display if (result === undefined) { - this.pathResult = 'Path not found'; - } else if (typeof result === 'object') { + this.pathResult = "Path not found"; + } else if (typeof result === "object") { this.pathResult = JSON.stringify(result, null, 2); } else { this.pathResult = String(result); } } catch (error) { this.error = `Error getting path: ${error.message}`; - this.pathResult = ''; + this.pathResult = ""; console.error(error); } }, - + // Clear path navigation clearPath() { - this.pathInput = ''; - this.pathResult = ''; + this.pathInput = ""; + this.pathResult = ""; }, - + // Show notification - showNotification(text, color = 'info', timeout = 3000) { + showNotification(text, color = "info", timeout = 3000) { this.notification = { show: true, text, color, - timeout + timeout, }; - + // Auto-hide notification after timeout setTimeout(() => { this.hideNotification(); }, timeout); }, - + // Hide notification hideNotification() { this.notification.show = false; - } + }, } -}); \ No newline at end of file +}); From 6ac1d3c0f3a37e7be074387739103cf197603ff0 Mon Sep 17 00:00:00 2001 From: William Summers Date: Mon, 28 Apr 2025 09:59:55 -0500 Subject: [PATCH 38/38] file reorg to align with best practices class renaming for consistency improved type usage --- dist/dts/XJX.d.ts | 8 +- .../dom-adapter.d.ts} | 12 +- dist/dts/core/config/config.d.ts | 2 +- .../json-to-xml-converter.d.ts} | 12 +- .../xml-to-json-converter.d.ts} | 12 +- .../BooleanTransformer.d.ts | 0 .../NumberTransformer.d.ts | 0 .../StringReplaceTransformer.d.ts | 0 .../TransformUtil.d.ts | 2 +- .../ValueTransformer.d.ts | 2 +- .../{transforms => transformers}/index.d.ts | 0 .../types/{types.d.ts => config-types.d.ts} | 2 +- dist/dts/core/types/dom-types.d.ts | 12 ++ .../types/{errors.d.ts => error-types.d.ts} | 0 dist/dts/core/types/json-types.d.ts | 31 ++++ .../utils/{JsonUtils.d.ts => json-utils.d.ts} | 7 +- .../utils/{XmlUtils.d.ts => xml-utils.d.ts} | 4 +- dist/dts/index.d.ts | 6 +- dist/index.d.ts | 4 +- dist/index.js | 152 ++++++++++-------- dist/index.js.map | 2 +- dist/stats.html | 2 +- dist/xjx.min.js | 2 +- dist/xjx.min.js.map | 2 +- dist/xjx.umd.js | 152 ++++++++++-------- dist/xjx.umd.js.map | 2 +- src/XJX.ts | 36 ++--- .../dom-adapter.ts} | 89 +++++----- src/core/config/config.ts | 2 +- .../json-to-xml-converter.ts} | 36 ++--- .../xml-to-json-converter.ts} | 38 ++--- .../BooleanTransformer.ts | 0 .../NumberTransformer.ts | 0 .../StringReplaceTransformer.ts | 0 .../TransformUtil.ts | 4 +- .../ValueTransformer.ts | 2 +- .../{transforms => transformers}/index.ts | 0 src/core/types/{types.ts => config-types.ts} | 2 +- src/core/types/dom-types.ts | 12 ++ src/core/types/{errors.ts => error-types.ts} | 0 src/core/types/json-types.ts | 37 +++++ .../utils/{JsonUtils.ts => json-utils.ts} | 7 +- src/core/utils/{XmlUtils.ts => xml-utils.ts} | 22 +-- src/index.ts | 6 +- 44 files changed, 415 insertions(+), 308 deletions(-) rename dist/dts/core/{DOMAdapter.d.ts => adapters/dom-adapter.d.ts} (82%) rename dist/dts/core/{JsonToXmlConverter.d.ts => converters/json-to-xml-converter.d.ts} (66%) rename dist/dts/core/{XmlToJsonConverter.d.ts => converters/xml-to-json-converter.d.ts} (66%) rename dist/dts/core/{transforms => transformers}/BooleanTransformer.d.ts (100%) rename dist/dts/core/{transforms => transformers}/NumberTransformer.d.ts (100%) rename dist/dts/core/{transforms => transformers}/StringReplaceTransformer.d.ts (100%) rename dist/dts/core/{transforms => transformers}/TransformUtil.d.ts (96%) rename dist/dts/core/{transforms => transformers}/ValueTransformer.d.ts (96%) rename dist/dts/core/{transforms => transformers}/index.d.ts (100%) rename dist/dts/core/types/{types.d.ts => config-types.d.ts} (92%) create mode 100644 dist/dts/core/types/dom-types.d.ts rename dist/dts/core/types/{errors.d.ts => error-types.d.ts} (100%) create mode 100644 dist/dts/core/types/json-types.d.ts rename dist/dts/core/utils/{JsonUtils.d.ts => json-utils.d.ts} (92%) rename dist/dts/core/utils/{XmlUtils.d.ts => xml-utils.d.ts} (95%) rename src/core/{DOMAdapter.ts => adapters/dom-adapter.ts} (82%) rename src/core/{JsonToXmlConverter.ts => converters/json-to-xml-converter.ts} (90%) rename src/core/{XmlToJsonConverter.ts => converters/xml-to-json-converter.ts} (89%) rename src/core/{transforms => transformers}/BooleanTransformer.ts (100%) rename src/core/{transforms => transformers}/NumberTransformer.ts (100%) rename src/core/{transforms => transformers}/StringReplaceTransformer.ts (100%) rename src/core/{transforms => transformers}/TransformUtil.ts (95%) rename src/core/{transforms => transformers}/ValueTransformer.ts (97%) rename src/core/{transforms => transformers}/index.ts (100%) rename src/core/types/{types.ts => config-types.ts} (93%) create mode 100644 src/core/types/dom-types.ts rename src/core/types/{errors.ts => error-types.ts} (100%) create mode 100644 src/core/types/json-types.ts rename src/core/utils/{JsonUtils.ts => json-utils.ts} (99%) rename src/core/utils/{XmlUtils.ts => xml-utils.ts} (91%) diff --git a/dist/dts/XJX.d.ts b/dist/dts/XJX.d.ts index 358a6c4..447cf64 100644 --- a/dist/dts/XJX.d.ts +++ b/dist/dts/XJX.d.ts @@ -1,9 +1,9 @@ -import { Configuration } from "./core/types/types"; -import { ValueTransformer } from "./core/transforms"; +import { Configuration } from "./core/types/config-types"; +import { ValueTransformer } from "./core/transformers"; export declare class XJX { private config; - private xmltojson; - private jsontoxml; + private xmlToJsonConverter; + private jsonToXmlConverter; private jsonUtil; private xmlUtil; /** diff --git a/dist/dts/core/DOMAdapter.d.ts b/dist/dts/core/adapters/dom-adapter.d.ts similarity index 82% rename from dist/dts/core/DOMAdapter.d.ts rename to dist/dts/core/adapters/dom-adapter.d.ts index acb3b33..3f99f64 100644 --- a/dist/dts/core/DOMAdapter.d.ts +++ b/dist/dts/core/adapters/dom-adapter.d.ts @@ -1,15 +1,8 @@ -interface NodeTypes { - ELEMENT_NODE: number; - TEXT_NODE: number; - CDATA_SECTION_NODE: number; - COMMENT_NODE: number; - PROCESSING_INSTRUCTION_NODE: number; - DOCUMENT_NODE: number; -} +import { NodeType } from '../types/dom-types'; export declare const DOMAdapter: { createParser: () => any; createSerializer: () => any; - nodeTypes: NodeTypes; + NodeType: typeof NodeType; parseFromString: (xmlString: string, contentType?: string) => any; serializeToString: (node: Node) => any; createDocument: () => any; @@ -37,4 +30,3 @@ export declare const DOMAdapter: { getNodeAttributes: (node: Element) => Record; cleanup: () => void; }; -export {}; diff --git a/dist/dts/core/config/config.d.ts b/dist/dts/core/config/config.d.ts index c4943ea..a52b30b 100644 --- a/dist/dts/core/config/config.d.ts +++ b/dist/dts/core/config/config.d.ts @@ -1,7 +1,7 @@ /** * Default configuration for the XJX library */ -import { Configuration } from '../types/types'; +import { Configuration } from '../types/config-types'; /** * Default configuration */ diff --git a/dist/dts/core/JsonToXmlConverter.d.ts b/dist/dts/core/converters/json-to-xml-converter.d.ts similarity index 66% rename from dist/dts/core/JsonToXmlConverter.d.ts rename to dist/dts/core/converters/json-to-xml-converter.d.ts index 2c2c4f9..6765362 100644 --- a/dist/dts/core/JsonToXmlConverter.d.ts +++ b/dist/dts/core/converters/json-to-xml-converter.d.ts @@ -1,16 +1,16 @@ /** - * JSONToXML class for converting JSON to XML with consistent namespace handling + * JsonToXmlConverter class for converting JSON to XML with consistent namespace handling */ -import { Configuration } from "./types/types"; +import { Configuration } from "../types/config-types"; /** - * JSONToXML for converting JSON to XML + * JsonToXmlConverter for converting JSON to XML */ -export declare class JSONToXML { +export declare class JsonToXmlConverter { private config; private xmlUtil; private transformUtil; /** - * Constructor for JSONToXML + * Constructor for JsonToXmlConverter * @param config Configuration options */ constructor(config: Configuration); @@ -19,7 +19,7 @@ export declare class JSONToXML { * @param jsonObj JSON object to convert * @returns XML string */ - serialize(jsonObj: Record): string; + convert(jsonObj: Record): string; /** * Convert JSON object to DOM node * @param jsonObj JSON object to convert diff --git a/dist/dts/core/XmlToJsonConverter.d.ts b/dist/dts/core/converters/xml-to-json-converter.d.ts similarity index 66% rename from dist/dts/core/XmlToJsonConverter.d.ts rename to dist/dts/core/converters/xml-to-json-converter.d.ts index 54e7ac9..4c5a7e7 100644 --- a/dist/dts/core/XmlToJsonConverter.d.ts +++ b/dist/dts/core/converters/xml-to-json-converter.d.ts @@ -1,16 +1,16 @@ /** - * XMLToJSON class for converting XML to JSON with consistent namespace handling + * XmlToJsonConverter class for converting XML to JSON with consistent namespace handling */ -import { Configuration } from "./types/types"; +import { Configuration } from "../types/config-types"; /** - * XMLToJSON Parser for converting XML to JSON + * XmlToJsonConverter Parser for converting XML to JSON */ -export declare class XMLToJSON { +export declare class XmlToJsonConverter { private config; private jsonUtil; private transformUtil; /** - * Constructor for XMLToJSON + * Constructor for XmlToJsonConverter * @param config Configuration options */ constructor(config: Configuration); @@ -19,7 +19,7 @@ export declare class XMLToJSON { * @param xmlString XML content as string * @returns JSON object representing the XML content */ - parse(xmlString: string): Record; + convert(xmlString: string): Record; /** * Convert a DOM node to JSON representation * @param node DOM node to convert diff --git a/dist/dts/core/transforms/BooleanTransformer.d.ts b/dist/dts/core/transformers/BooleanTransformer.d.ts similarity index 100% rename from dist/dts/core/transforms/BooleanTransformer.d.ts rename to dist/dts/core/transformers/BooleanTransformer.d.ts diff --git a/dist/dts/core/transforms/NumberTransformer.d.ts b/dist/dts/core/transformers/NumberTransformer.d.ts similarity index 100% rename from dist/dts/core/transforms/NumberTransformer.d.ts rename to dist/dts/core/transformers/NumberTransformer.d.ts diff --git a/dist/dts/core/transforms/StringReplaceTransformer.d.ts b/dist/dts/core/transformers/StringReplaceTransformer.d.ts similarity index 100% rename from dist/dts/core/transforms/StringReplaceTransformer.d.ts rename to dist/dts/core/transformers/StringReplaceTransformer.d.ts diff --git a/dist/dts/core/transforms/TransformUtil.d.ts b/dist/dts/core/transformers/TransformUtil.d.ts similarity index 96% rename from dist/dts/core/transforms/TransformUtil.d.ts rename to dist/dts/core/transformers/TransformUtil.d.ts index 0045073..a634de9 100644 --- a/dist/dts/core/transforms/TransformUtil.d.ts +++ b/dist/dts/core/transformers/TransformUtil.d.ts @@ -1,7 +1,7 @@ /** * Utilities for applying value transformations */ -import { Configuration } from '../types/types'; +import { Configuration } from '../types/config-types'; import { TransformContext, TransformDirection } from './ValueTransformer'; /** * Utility for applying value transformations diff --git a/dist/dts/core/transforms/ValueTransformer.d.ts b/dist/dts/core/transformers/ValueTransformer.d.ts similarity index 96% rename from dist/dts/core/transforms/ValueTransformer.d.ts rename to dist/dts/core/transformers/ValueTransformer.d.ts index 40e32e2..e9290f2 100644 --- a/dist/dts/core/transforms/ValueTransformer.d.ts +++ b/dist/dts/core/transformers/ValueTransformer.d.ts @@ -1,7 +1,7 @@ /** * Value transformation types and base class for the XJX library */ -import { Configuration } from '../types/types'; +import { Configuration } from '../types/config-types'; /** * Direction of the transformation */ diff --git a/dist/dts/core/transforms/index.d.ts b/dist/dts/core/transformers/index.d.ts similarity index 100% rename from dist/dts/core/transforms/index.d.ts rename to dist/dts/core/transformers/index.d.ts diff --git a/dist/dts/core/types/types.d.ts b/dist/dts/core/types/config-types.d.ts similarity index 92% rename from dist/dts/core/types/types.d.ts rename to dist/dts/core/types/config-types.d.ts index 9eb379b..4668094 100644 --- a/dist/dts/core/types/types.d.ts +++ b/dist/dts/core/types/config-types.d.ts @@ -1,7 +1,7 @@ /** * Type definitions for the XJX library */ -import { ValueTransformer } from '../transforms/ValueTransformer'; +import { ValueTransformer } from '../transformers/ValueTransformer'; /** * Configuration interface for the library */ diff --git a/dist/dts/core/types/dom-types.d.ts b/dist/dts/core/types/dom-types.d.ts new file mode 100644 index 0000000..7fa07a2 --- /dev/null +++ b/dist/dts/core/types/dom-types.d.ts @@ -0,0 +1,12 @@ +/** + * DOM node types as an enum for better type safety + */ +export declare enum NodeType { + ELEMENT_NODE = 1, + ATTRIBUTE_NODE = 2, + TEXT_NODE = 3, + CDATA_SECTION_NODE = 4, + PROCESSING_INSTRUCTION_NODE = 7, + COMMENT_NODE = 8, + DOCUMENT_NODE = 9 +} diff --git a/dist/dts/core/types/errors.d.ts b/dist/dts/core/types/error-types.d.ts similarity index 100% rename from dist/dts/core/types/errors.d.ts rename to dist/dts/core/types/error-types.d.ts diff --git a/dist/dts/core/types/json-types.d.ts b/dist/dts/core/types/json-types.d.ts new file mode 100644 index 0000000..12d03a3 --- /dev/null +++ b/dist/dts/core/types/json-types.d.ts @@ -0,0 +1,31 @@ +/** + * Basic JSON primitive types + */ +export type JSONPrimitive = string | number | boolean | null; +/** + * JSON array type (recursive definition) + */ +export type JSONArray = JSONValue[]; +/** + * JSON object type (recursive definition) + */ +export interface JSONObject { + [key: string]: JSONValue; +} +/** + * Combined JSON value type that can be any valid JSON structure + */ +export type JSONValue = JSONPrimitive | JSONArray | JSONObject; +/** + * Type for XML-in-JSON structure based on the library's configuration + * This is a generic template that will use the actual property names from config + */ +export interface XMLJSONNode { + [tagName: string]: XMLJSONElement; +} +/** + * Structure of an XML element in JSON representation + */ +export interface XMLJSONElement { + [key: string]: JSONValue | XMLJSONNode[]; +} diff --git a/dist/dts/core/utils/JsonUtils.d.ts b/dist/dts/core/utils/json-utils.d.ts similarity index 92% rename from dist/dts/core/utils/JsonUtils.d.ts rename to dist/dts/core/utils/json-utils.d.ts index 9abb93e..a093995 100644 --- a/dist/dts/core/utils/JsonUtils.d.ts +++ b/dist/dts/core/utils/json-utils.d.ts @@ -1,8 +1,9 @@ /** * JSONUtil - Utility functions for JSON processing */ -import { Configuration } from "../types/types"; -export declare class JSONUtil { +import { Configuration } from "../types/config-types"; +import { JSONValue } from "../types/json-types"; +export declare class JsonUtil { private config; /** * Constructor for JSONUtil @@ -18,7 +19,7 @@ export declare class JSONUtil { * @param fallback Value to return if the path does not resolve * @returns Retrieved value or fallback */ - getPath(obj: Record, path: string, fallback?: any): any; + getPath(obj: Record, path: string, fallback?: JSONValue): any; /** * Resolves a single path segment in the context of a JSON object. * Falls back to searching children for matching keys. diff --git a/dist/dts/core/utils/XmlUtils.d.ts b/dist/dts/core/utils/xml-utils.d.ts similarity index 95% rename from dist/dts/core/utils/XmlUtils.d.ts rename to dist/dts/core/utils/xml-utils.d.ts index 5ca0a0d..9b2ed15 100644 --- a/dist/dts/core/utils/XmlUtils.d.ts +++ b/dist/dts/core/utils/xml-utils.d.ts @@ -1,5 +1,5 @@ -import { Configuration } from "../types/types"; -export declare class XMLUtil { +import { Configuration } from "../types/config-types"; +export declare class XmlUtil { private config; /** * Constructor for XMLUtil diff --git a/dist/dts/index.d.ts b/dist/dts/index.d.ts index 2aa2f9d..8c7b962 100644 --- a/dist/dts/index.d.ts +++ b/dist/dts/index.d.ts @@ -1,7 +1,7 @@ import { XJX } from './XJX'; export { XJX }; -export { Configuration } from './core/types/types'; +export { Configuration } from './core/types/config-types'; export { DEFAULT_CONFIG } from './core/config/config'; -export { XJXError } from './core/types/errors'; -export { ValueTransformer } from './core/transforms/ValueTransformer'; +export { XJXError } from './core/types/error-types'; +export { ValueTransformer } from './core/transformers/ValueTransformer'; export default XJX; diff --git a/dist/index.d.ts b/dist/index.d.ts index 70c539a..03690ce 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -88,8 +88,8 @@ interface Configuration { declare class XJX { private config; - private xmltojson; - private jsontoxml; + private xmlToJsonConverter; + private jsonToXmlConverter; private jsonUtil; private xmlUtil; /** diff --git a/dist/index.js b/dist/index.js index 91f0921..9393a0f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -11,6 +11,20 @@ class XJXError extends Error { } } +/** + * DOM node types as an enum for better type safety + */ +var NodeType; +(function (NodeType) { + NodeType[NodeType["ELEMENT_NODE"] = 1] = "ELEMENT_NODE"; + NodeType[NodeType["ATTRIBUTE_NODE"] = 2] = "ATTRIBUTE_NODE"; + NodeType[NodeType["TEXT_NODE"] = 3] = "TEXT_NODE"; + NodeType[NodeType["CDATA_SECTION_NODE"] = 4] = "CDATA_SECTION_NODE"; + NodeType[NodeType["PROCESSING_INSTRUCTION_NODE"] = 7] = "PROCESSING_INSTRUCTION_NODE"; + NodeType[NodeType["COMMENT_NODE"] = 8] = "COMMENT_NODE"; + NodeType[NodeType["DOCUMENT_NODE"] = 9] = "DOCUMENT_NODE"; +})(NodeType || (NodeType = {})); + /** * DOM Environment provider with unified interface for browser and Node.js */ @@ -18,7 +32,7 @@ const DOMAdapter = (() => { // Environment-specific DOM implementation let domParser; let xmlSerializer; - let nodeTypes; + // let nodeTypes: NodeTypes; let docImplementation; let jsdomInstance = null; try { @@ -31,14 +45,14 @@ const DOMAdapter = (() => { }); domParser = jsdomInstance.window.DOMParser; xmlSerializer = jsdomInstance.window.XMLSerializer; - nodeTypes = { - ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE, - TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE, - CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE, - COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE, - PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE, - DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line - }; + // nodeTypes = { + // ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE, + // TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE, + // CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE, + // COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE, + // PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE, + // DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line + // }; docImplementation = jsdomInstance.window.document.implementation; } catch (jsdomError) { @@ -48,14 +62,14 @@ const DOMAdapter = (() => { domParser = DOMParser; xmlSerializer = XMLSerializer; // Standard DOM node types - nodeTypes = { - ELEMENT_NODE: 1, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - COMMENT_NODE: 8, - PROCESSING_INSTRUCTION_NODE: 7, - DOCUMENT_NODE: 9, - }; + // nodeTypes = { + // ELEMENT_NODE: 1, + // TEXT_NODE: 3, + // CDATA_SECTION_NODE: 4, + // COMMENT_NODE: 8, + // PROCESSING_INSTRUCTION_NODE: 7, + // DOCUMENT_NODE: 9, + // }; const implementation = new DOMImplementation(); docImplementation = implementation; } @@ -74,14 +88,14 @@ const DOMAdapter = (() => { } domParser = window.DOMParser; xmlSerializer = window.XMLSerializer; - nodeTypes = { - ELEMENT_NODE: Node.ELEMENT_NODE, - TEXT_NODE: Node.TEXT_NODE, - CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE, - COMMENT_NODE: Node.COMMENT_NODE, - PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE, - DOCUMENT_NODE: Node.DOCUMENT_NODE, - }; + // nodeTypes = { + // ELEMENT_NODE: Node.ELEMENT_NODE, + // TEXT_NODE: Node.TEXT_NODE, + // CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE, + // COMMENT_NODE: Node.COMMENT_NODE, + // PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE, + // DOCUMENT_NODE: Node.DOCUMENT_NODE, + // }; docImplementation = document.implementation; } } @@ -105,7 +119,7 @@ const DOMAdapter = (() => { throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`); } }, - nodeTypes, + NodeType, parseFromString: (xmlString, contentType = 'text/xml') => { try { const parser = new domParser(); @@ -259,11 +273,11 @@ const DOMAdapter = (() => { */ getNodeTypeName: (nodeType) => { switch (nodeType) { - case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE'; - case nodeTypes.TEXT_NODE: return 'TEXT_NODE'; - case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE'; - case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE'; - case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE'; + case NodeType.ELEMENT_NODE: return 'ELEMENT_NODE'; + case NodeType.TEXT_NODE: return 'TEXT_NODE'; + case NodeType.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE'; + case NodeType.COMMENT_NODE: return 'COMMENT_NODE'; + case NodeType.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE'; default: return `UNKNOWN_NODE_TYPE(${nodeType})`; } }, @@ -287,7 +301,7 @@ const DOMAdapter = (() => { }; })(); -class JSONUtil { +class JsonUtil { /** * Constructor for JSONUtil * @param config Configuration options @@ -304,7 +318,7 @@ class JSONUtil { * @param fallback Value to return if the path does not resolve * @returns Retrieved value or fallback */ - getPath(obj, path, fallback = undefined) { + getPath(obj, path, fallback) { const segments = path.split("."); let current = obj; for (const segment of segments) { @@ -828,16 +842,16 @@ class TransformUtil { } /** - * XMLToJSON Parser for converting XML to JSON + * XmlToJsonConverter Parser for converting XML to JSON */ -class XMLToJSON { +class XmlToJsonConverter { /** - * Constructor for XMLToJSON + * Constructor for XmlToJsonConverter * @param config Configuration options */ constructor(config) { this.config = config; - this.jsonUtil = new JSONUtil(this.config); + this.jsonUtil = new JsonUtil(this.config); this.transformUtil = new TransformUtil(this.config); } /** @@ -845,7 +859,7 @@ class XMLToJSON { * @param xmlString XML content as string * @returns JSON object representing the XML content */ - parse(xmlString) { + convert(xmlString) { try { const xmlDoc = DOMAdapter.parseFromString(xmlString, "text/xml"); // Check for parsing errors @@ -869,7 +883,7 @@ class XMLToJSON { nodeToJson(node, parentContext, path = "") { const result = {}; // Handle element nodes - if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { + if (node.nodeType === DOMAdapter.NodeType.ELEMENT_NODE) { const element = node; // Use localName instead of nodeName to strip namespace prefix const nodeName = element.localName || @@ -951,7 +965,7 @@ class XMLToJSON { for (let i = 0; i < element.childNodes.length; i++) { const child = element.childNodes[i]; // Text nodes - only process if preserveTextNodes is true - if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) { + if (child.nodeType === DOMAdapter.NodeType.TEXT_NODE) { if (this.config.preserveTextNodes) { let text = child.nodeValue || ""; // Skip whitespace-only text nodes if whitespace preservation is disabled @@ -973,7 +987,7 @@ class XMLToJSON { } } // CDATA sections - else if (child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE && + else if (child.nodeType === DOMAdapter.NodeType.CDATA_SECTION_NODE && this.config.preserveCDATA) { // Create CDATA context const cdataContext = this.transformUtil.createContext('xml-to-json', '#cdata', child.nodeType, { @@ -987,7 +1001,7 @@ class XMLToJSON { }); } // Comments - else if (child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE && + else if (child.nodeType === DOMAdapter.NodeType.COMMENT_NODE && this.config.preserveComments) { children.push({ [commentsKey]: child.nodeValue || "", @@ -995,7 +1009,7 @@ class XMLToJSON { } // Processing instructions else if (child.nodeType === - DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE && + DOMAdapter.NodeType.PROCESSING_INSTRUCTION_NODE && this.config.preserveProcessingInstr) { children.push({ [instructionKey]: { @@ -1005,7 +1019,7 @@ class XMLToJSON { }); } // Element nodes (recursive) - else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) { + else if (child.nodeType === DOMAdapter.NodeType.ELEMENT_NODE) { children.push(this.nodeToJson(child, context, currentPath)); } } @@ -1075,7 +1089,7 @@ class XMLToJSON { /** * XMLUtil - Utility functions for XML processing */ -class XMLUtil { +class XmlUtil { /** * Constructor for XMLUtil * @param config Configuration options @@ -1096,7 +1110,7 @@ class XMLUtil { const serializer = (node, level = 0) => { const pad = INDENT.repeat(level); switch (node.nodeType) { - case DOMAdapter.nodeTypes.ELEMENT_NODE: { + case DOMAdapter.NodeType.ELEMENT_NODE: { const el = node; const tagName = el.tagName; const attrs = Array.from(el.attributes) @@ -1110,7 +1124,7 @@ class XMLUtil { // Single text node: print inline if (children.length === 0 || (children.length === 1 && - children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE && + children[0].nodeType === DOMAdapter.NodeType.TEXT_NODE && children[0].textContent?.trim() === "")) { // Empty or whitespace-only return `${pad}<${tagName}${attrs ? " " + attrs : ""}>\n`; @@ -1120,18 +1134,18 @@ class XMLUtil { .join(""); return `${pad}${openTag}\n${inner}${pad}\n`; } - case DOMAdapter.nodeTypes.TEXT_NODE: { + case DOMAdapter.NodeType.TEXT_NODE: { const text = node.textContent?.trim(); return text ? `${pad}${text}\n` : ""; } - case DOMAdapter.nodeTypes.CDATA_SECTION_NODE: + case DOMAdapter.NodeType.CDATA_SECTION_NODE: return `${pad}\n`; - case DOMAdapter.nodeTypes.COMMENT_NODE: + case DOMAdapter.NodeType.COMMENT_NODE: return `${pad}\n`; - case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE: + case DOMAdapter.NodeType.PROCESSING_INSTRUCTION_NODE: const pi = node; return `${pad}\n`; - case DOMAdapter.nodeTypes.DOCUMENT_NODE: + case DOMAdapter.NodeType.DOCUMENT_NODE: return Array.from(node.childNodes) .map((child) => serializer(child, level)) .join(""); @@ -1264,16 +1278,16 @@ class XMLUtil { } /** - * JSONToXML for converting JSON to XML + * JsonToXmlConverter for converting JSON to XML */ -class JSONToXML { +class JsonToXmlConverter { /** - * Constructor for JSONToXML + * Constructor for JsonToXmlConverter * @param config Configuration options */ constructor(config) { this.config = config; - this.xmlUtil = new XMLUtil(this.config); + this.xmlUtil = new XmlUtil(this.config); this.transformUtil = new TransformUtil(this.config); } /** @@ -1281,7 +1295,7 @@ class JSONToXML { * @param jsonObj JSON object to convert * @returns XML string */ - serialize(jsonObj) { + convert(jsonObj) { try { const doc = DOMAdapter.createDocument(); const rootElement = this.jsonToNode(jsonObj, doc); @@ -1338,7 +1352,7 @@ class JSONToXML { const ns = nodeData[namespaceKey]; const prefix = nodeData[prefixKey]; // Create context for this node - const context = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.ELEMENT_NODE, { + const context = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.NodeType.ELEMENT_NODE, { path: currentPath, namespace: ns, prefix: prefix, @@ -1370,7 +1384,7 @@ class JSONToXML { return; const attrData = attrObj[attrName]; // Create attribute context - const attrContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.ELEMENT_NODE, { + const attrContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.NodeType.ELEMENT_NODE, { path: `${currentPath}.${attrName}`, namespace: attrData[namespaceKey], prefix: attrData[prefixKey], @@ -1393,7 +1407,7 @@ class JSONToXML { // Process simple text value if (nodeData[valueKey] !== undefined) { // Apply transformations to text value - const textContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.nodeTypes.TEXT_NODE, { + const textContext = this.transformUtil.createContext('json-to-xml', nodeName, DOMAdapter.NodeType.TEXT_NODE, { path: `${currentPath}.#text`, namespace: ns, prefix: prefix, @@ -1415,7 +1429,7 @@ class JSONToXML { if (child[valueKey] !== undefined && this.config.preserveTextNodes) { // Apply transformations to text node - const textContext = this.transformUtil.createContext('json-to-xml', '#text', DOMAdapter.nodeTypes.TEXT_NODE, { + const textContext = this.transformUtil.createContext('json-to-xml', '#text', DOMAdapter.NodeType.TEXT_NODE, { path: `${currentPath}.#text`, parent: context }); @@ -1426,7 +1440,7 @@ class JSONToXML { else if (child[cdataKey] !== undefined && this.config.preserveCDATA) { // Apply transformations to CDATA - const cdataContext = this.transformUtil.createContext('json-to-xml', '#cdata', DOMAdapter.nodeTypes.CDATA_SECTION_NODE, { + const cdataContext = this.transformUtil.createContext('json-to-xml', '#cdata', DOMAdapter.NodeType.CDATA_SECTION_NODE, { path: `${currentPath}.#cdata`, parent: context }); @@ -1504,17 +1518,17 @@ class XJX { */ constructor(config = {}) { // First create a jsonUtil instance with default config to use its methods - this.jsonUtil = new JSONUtil(DEFAULT_CONFIG); + this.jsonUtil = new JsonUtil(DEFAULT_CONFIG); // Create a deep clone of the default config const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG); // Deep merge with the provided config this.config = this.jsonUtil.deepMerge(defaultClone, config); // Re-initialize jsonUtil with the merged config - this.jsonUtil = new JSONUtil(this.config); + this.jsonUtil = new JsonUtil(this.config); // Initialize other components - this.xmlUtil = new XMLUtil(this.config); - this.xmltojson = new XMLToJSON(this.config); - this.jsontoxml = new JSONToXML(this.config); + this.xmlUtil = new XmlUtil(this.config); + this.xmlToJsonConverter = new XmlToJsonConverter(this.config); + this.jsonToXmlConverter = new JsonToXmlConverter(this.config); } /** * Convert XML string to JSON @@ -1522,7 +1536,7 @@ class XJX { * @returns JSON object representing the XML content */ xmlToJson(xmlString) { - return this.xmltojson.parse(xmlString); + return this.xmlToJsonConverter.convert(xmlString); } /** * Convert JSON object back to XML string @@ -1530,7 +1544,7 @@ class XJX { * @returns XML string */ jsonToXml(jsonObj) { - return this.jsontoxml.serialize(jsonObj); + return this.jsonToXmlConverter.convert(jsonObj); } /** * Pretty print an XML string diff --git a/dist/index.js.map b/dist/index.js.map index 1d3e3a5..7da0703 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../../src/core/types/errors.ts","../../src/core/DOMAdapter.ts","../../src/core/utils/JsonUtils.ts","../../src/core/transforms/TransformUtil.ts","../../src/core/XmlToJsonConverter.ts","../../src/core/utils/XmlUtils.ts","../../src/core/JsonToXmlConverter.ts","../../src/core/config/config.ts","../../src/XJX.ts","../../src/core/transforms/ValueTransformer.ts","../../src/index.ts"],"sourcesContent":["/**\n * Error classes for the XJX library\n */\n\n/**\n * Base error class\n */\nexport class XJXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'XMLToJSONError';\n }\n}\n\n/**\n * Error for XML parsing issues\n */\nexport class XmlToJsonError extends XJXError {\n constructor(message: string) {\n super(`XML parse error: ${message}`);\n this.name = 'XmlToJsonError';\n }\n}\n\n/**\n * Error for XML serialization issues\n */\nexport class JsonToXmlError extends XJXError {\n constructor(message: string) {\n super(`XML serialization error: ${message}`);\n this.name = 'JsonToXmlError';\n }\n}\n\n/**\n * Error for environment incompatibility\n */\nexport class EnvironmentError extends XJXError {\n constructor(message: string) {\n super(`Environment error: ${message}`);\n this.name = 'EnvironmentError';\n }\n}\n\n/**\n * Error for invalid configuration\n */\nexport class ConfigurationError extends XJXError {\n constructor(message: string) {\n super(`Configuration error: ${message}`);\n this.name = 'ConfigurationError';\n }\n}","/**\n * DOM Environment provider with unified interface for browser and Node.js\n */\nimport { XJXError } from './types/errors';\n\ninterface NodeTypes {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n}\n\ninterface DOMWindow {\n DOMParser: any;\n XMLSerializer: any;\n Node: {\n ELEMENT_NODE: number;\n TEXT_NODE: number;\n CDATA_SECTION_NODE: number;\n COMMENT_NODE: number;\n PROCESSING_INSTRUCTION_NODE: number;\n DOCUMENT_NODE: number; \n };\n document: Document;\n close?: () => void; \n}\n\ninterface JSDOMInstance {\n window: DOMWindow;\n}\n\nexport const DOMAdapter = (() => {\n // Environment-specific DOM implementation\n let domParser: any;\n let xmlSerializer: any;\n let nodeTypes: NodeTypes;\n let docImplementation: any;\n let jsdomInstance: JSDOMInstance | null = null;\n\n try {\n if (typeof window === \"undefined\") {\n // Node.js environment - try JSDOM first\n try {\n const { JSDOM } = require(\"jsdom\");\n jsdomInstance = new JSDOM(\"\", {\n contentType: \"text/xml\",\n }) as JSDOMInstance;\n\n domParser = jsdomInstance.window.DOMParser;\n xmlSerializer = jsdomInstance.window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE,\n TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE,\n CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE,\n COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line\n };\n docImplementation = jsdomInstance.window.document.implementation;\n } catch (jsdomError) {\n // Fall back to xmldom if JSDOM isn't available\n try {\n const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom');\n domParser = DOMParser;\n xmlSerializer = XMLSerializer;\n // Standard DOM node types\n nodeTypes = {\n ELEMENT_NODE: 1,\n TEXT_NODE: 3,\n CDATA_SECTION_NODE: 4,\n COMMENT_NODE: 8,\n PROCESSING_INSTRUCTION_NODE: 7,\n DOCUMENT_NODE: 9, \n };\n const implementation = new DOMImplementation();\n docImplementation = implementation;\n } catch (xmldomError) {\n throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`);\n }\n }\n } else {\n // Browser environment\n if (!window.DOMParser) {\n throw new XJXError(\"DOMParser is not available in this environment\");\n }\n\n if (!window.XMLSerializer) {\n throw new XJXError(\"XMLSerializer is not available in this environment\");\n }\n\n domParser = window.DOMParser;\n xmlSerializer = window.XMLSerializer;\n nodeTypes = {\n ELEMENT_NODE: Node.ELEMENT_NODE,\n TEXT_NODE: Node.TEXT_NODE,\n CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE,\n COMMENT_NODE: Node.COMMENT_NODE,\n PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE,\n DOCUMENT_NODE: Node.DOCUMENT_NODE, \n };\n docImplementation = document.implementation;\n }\n } catch (error) {\n throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n return {\n createParser: () => {\n try {\n return new domParser();\n } catch (error) {\n throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createSerializer: () => {\n try {\n return new xmlSerializer();\n } catch (error) {\n throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n nodeTypes,\n \n parseFromString: (xmlString: string, contentType: string = 'text/xml') => {\n try {\n const parser = new domParser();\n return parser.parseFromString(xmlString, contentType);\n } catch (error) {\n throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n serializeToString: (node: Node) => {\n try {\n const serializer = new xmlSerializer();\n return serializer.serializeToString(node);\n } catch (error) {\n throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createDocument: () => {\n try {\n // For browsers, create a document with a root element to avoid issues\n if (typeof window !== \"undefined\") {\n const parser = new domParser();\n return parser.parseFromString('', 'text/xml');\n } else {\n return docImplementation.createDocument(null, null, null);\n }\n } catch (error) {\n throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElement: (tagName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElement(tagName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElement(tagName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElementNS: (namespaceURI: string, qualifiedName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElementNS(namespaceURI, qualifiedName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElementNS(namespaceURI, qualifiedName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createTextNode: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createTextNode(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createTextNode(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createCDATASection: (data: string) => {\n try {\n // For browser compatibility, use document.implementation to create CDATA\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createComment: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createComment(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createComment(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createProcessingInstruction: (target: string, data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n // New helper methods\n \n /**\n * Creates a proper namespace qualified attribute\n */\n setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => {\n try {\n if (namespaceURI) {\n element.setAttributeNS(namespaceURI, qualifiedName, value);\n } else {\n element.setAttribute(qualifiedName, value);\n }\n } catch (error) {\n throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n /**\n * Check if an object is a DOM node\n */\n isNode: (obj: any): boolean => {\n try {\n return obj && typeof obj === 'object' && typeof obj.nodeType === 'number';\n } catch (error) {\n return false;\n }\n },\n \n /**\n * Get DOM node type as string for debugging\n */\n getNodeTypeName: (nodeType: number): string => {\n switch (nodeType) {\n case nodeTypes.ELEMENT_NODE: return 'ELEMENT_NODE';\n case nodeTypes.TEXT_NODE: return 'TEXT_NODE';\n case nodeTypes.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE';\n case nodeTypes.COMMENT_NODE: return 'COMMENT_NODE';\n case nodeTypes.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE';\n default: return `UNKNOWN_NODE_TYPE(${nodeType})`;\n }\n },\n \n /**\n * Get all node attributes as an object\n */\n getNodeAttributes: (node: Element): Record => {\n const result: Record = {};\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n result[attr.name] = attr.value;\n }\n return result;\n },\n \n // Cleanup method (mainly for JSDOM)\n cleanup: () => {\n if (jsdomInstance && typeof jsdomInstance.window.close === 'function') {\n jsdomInstance.window.close();\n }\n }\n };\n})();","/**\n * JSONUtil - Utility functions for JSON processing\n */\nimport { Configuration } from \"../types/types\";\n\nexport class JSONUtil {\n private config: Configuration;\n\n /**\n * Constructor for JSONUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * Automatically traverses into children arrays and flattens results.\n *\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns Retrieved value or fallback\n */\n getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n const segments = path.split(\".\");\n let current: any = obj;\n\n for (const segment of segments) {\n if (Array.isArray(current)) {\n // Apply the segment to each array element and flatten results\n const results = current\n .map((item) => this.resolveSegment(item, segment))\n .flat()\n .filter((v) => v !== undefined);\n current = results.length > 0 ? results : undefined;\n } else {\n current = this.resolveSegment(current, segment);\n }\n\n if (current === undefined) return fallback;\n }\n\n // Collapse singleton arrays\n if (Array.isArray(current) && current.length === 1) {\n return current[0];\n }\n\n return current !== undefined ? current : fallback;\n }\n\n /**\n * Resolves a single path segment in the context of a JSON object.\n * Falls back to searching children for matching keys.\n *\n * @param obj The current object\n * @param segment The path segment to resolve\n * @returns Resolved value or undefined\n */\n private resolveSegment(obj: any, segment: string): any {\n if (obj == null || typeof obj !== \"object\") return undefined;\n\n // Direct property access\n if (segment in obj) {\n return obj[segment];\n }\n\n // Check if this is a special property name that matches the config\n if (\n segment === this.config.propNames.value ||\n segment === this.config.propNames.children ||\n segment === this.config.propNames.attributes ||\n segment === this.config.propNames.namespace ||\n segment === this.config.propNames.prefix ||\n segment === this.config.propNames.cdata ||\n segment === this.config.propNames.comments ||\n segment === this.config.propNames.instruction ||\n segment === this.config.propNames.target\n ) {\n const configKey = Object.entries(this.config.propNames).find(\n ([_, value]) => value === segment\n )?.[0];\n\n if (configKey && obj[segment] !== undefined) {\n return obj[segment];\n }\n }\n\n // Check children for objects that contain the segment\n const childrenKey = this.config.propNames.children;\n const children = obj[childrenKey];\n if (Array.isArray(children)) {\n const matches = children\n .map((child) => (segment in child ? child[segment] : undefined))\n .filter((v) => v !== undefined);\n return matches.length > 0 ? matches : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Converts a plain JSON object to the XML-like JSON structure.\n * Optionally wraps the result in a root element with attributes and namespaces.\n *\n * @param obj Standard JSON object\n * @param root Optional root element configuration (either a string or object with $ keys)\n * @returns XML-like JSON object\n */\n objectToXJX(obj: any, root?: any): any {\n const wrappedObject = this.wrapObject(obj);\n\n if (typeof root === \"string\") {\n // Root is a simple string: wrap result with this root tag\n return { [root]: wrappedObject };\n }\n\n if (root && typeof root === \"object\") {\n // Handle root with config-based keys\n const elementName = root.name || \"root\"; // Default to \"root\" if no name is provided\n const prefix = root[this.config.propNames.prefix] || \"\";\n const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName;\n\n const result: any = {\n [qualifiedName]: {},\n };\n\n // Add attributes to the root element if defined\n const attrsKey = this.config.propNames.attributes;\n if (root[attrsKey] && Array.isArray(root[attrsKey])) {\n result[qualifiedName][attrsKey] = root[attrsKey];\n }\n\n // Merge existing children with the new generated children\n const childrenKey = this.config.propNames.children;\n const children = root[childrenKey] ? root[childrenKey] : [];\n result[qualifiedName][childrenKey] = [\n ...children,\n { [elementName]: wrappedObject },\n ];\n\n // Add namespace and prefix if defined\n const nsKey = this.config.propNames.namespace;\n if (root[nsKey]) {\n result[qualifiedName][nsKey] = root[nsKey];\n }\n\n if (prefix && root[nsKey]) {\n result[qualifiedName][`xmlns:${prefix}`] = root[nsKey];\n }\n\n return result;\n }\n\n // Default behavior if no root is provided\n return wrappedObject;\n }\n\n /**\n * Wraps a standard JSON value in the XML-like JSON structure\n * @param value Value to wrap\n * @returns Wrapped value\n */\n private wrapObject(value: any): any {\n const valKey = this.config.propNames.value;\n const childrenKey = this.config.propNames.children;\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return { [valKey]: value };\n }\n\n if (Array.isArray(value)) {\n // For arrays, wrap each item and return as a children-style array of repeated elements\n return {\n [childrenKey]: value.map((item) => {\n return this.wrapObject(item);\n }),\n };\n }\n\n if (typeof value === \"object\") {\n // It's an object: wrap its properties in children\n const children = Object.entries(value).map(([key, val]) => ({\n [key]: this.wrapObject(val),\n }));\n\n return { [childrenKey]: children };\n }\n\n return undefined; // Fallback for unhandled types\n }\n\n /**\n * Check if an object is empty\n * @param value Value to check\n * @returns true if empty\n */\n isEmpty(value: any): boolean {\n if (value == null) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n }\n\n /**\n * Safely stringify JSON for debugging\n * @param obj Object to stringify\n * @param indent Optional indentation level\n * @returns JSON string representation\n */\n safeStringify(obj: any, indent: number = 2): string {\n try {\n return JSON.stringify(obj, null, indent);\n } catch (error) {\n return \"[Cannot stringify object]\";\n }\n }\n\n /**\n * Deep clone an object\n * @param obj Object to clone\n * @returns Cloned object\n */\n deepClone(obj: any): any {\n try {\n return JSON.parse(JSON.stringify(obj));\n } catch (error) {\n throw new Error(\n `Failed to deep clone object: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Deep merge two objects with proper type handling\n * @param target Target object\n * @param source Source object\n * @returns Merged object (target is modified)\n */\n deepMerge(target: T, source: Partial): T {\n if (!source || typeof source !== \"object\" || source === null) {\n return target;\n }\n\n if (!target || typeof target !== \"object\" || target === null) {\n return source as unknown as T;\n }\n\n Object.keys(source).forEach((key) => {\n const sourceValue = source[key as keyof Partial];\n const targetValue = target[key as keyof T];\n\n // If both source and target values are objects, recursively merge them\n if (\n sourceValue !== null &&\n targetValue !== null &&\n typeof sourceValue === \"object\" &&\n typeof targetValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n !Array.isArray(targetValue)\n ) {\n // Recursively merge the nested objects\n (target as any)[key] = this.deepMerge(targetValue, sourceValue as any);\n } else {\n // Otherwise just replace the value\n (target as any)[key] = sourceValue;\n }\n });\n\n return target;\n }\n\n /**\n * Generates a JSON schema that matches the current configuration\n * @returns JSON schema object\n */\n generateJsonSchema(): Record {\n try {\n const propNames = this.config.propNames;\n const compact = this.config.outputOptions.compact || false;\n const preserveNamespaces = this.config.preserveNamespaces;\n const preserveComments = this.config.preserveComments;\n const preserveCDATA = this.config.preserveCDATA;\n const preserveProcessingInstr = this.config.preserveProcessingInstr;\n const preserveTextNodes = this.config.preserveTextNodes;\n const preserveWhitespace = this.config.preserveWhitespace;\n const preserveAttributes = this.config.preserveAttributes;\n\n // Determine which properties are required based on the configuration\n const requiredProps: string[] = [];\n\n if (!compact) {\n // Only add collections as required if they're preserved in the config\n if (preserveAttributes) requiredProps.push(propNames.attributes);\n\n if (preserveCDATA) requiredProps.push(propNames.cdata);\n if (preserveComments) requiredProps.push(propNames.comments);\n if (preserveProcessingInstr) requiredProps.push(propNames.instruction);\n requiredProps.push(propNames.children);\n\n if (preserveTextNodes) {\n requiredProps.push(propNames.value);\n\n if (preserveNamespaces) {\n requiredProps.push(propNames.namespace);\n // Note: prefix is not required as it may not be present for all elements\n }\n }\n }\n\n // Create schema for element properties\n const elementProperties: Record = {};\n\n // Add namespace property if preserving namespaces\n if (preserveNamespaces) {\n elementProperties[propNames.namespace] = {\n description: \"Namespace URI of the element\",\n type: \"string\",\n };\n\n // Add prefix property if preserving namespaces\n elementProperties[propNames.prefix] = {\n description: \"Namespace prefix of the element\",\n type: \"string\",\n };\n }\n\n // Add value property if preserving text nodes\n if (preserveTextNodes) {\n elementProperties[propNames.value] = {\n description: \"Text content of the element\",\n type: \"string\",\n };\n }\n\n // Add attributes property\n if (preserveAttributes) {\n elementProperties[propNames.attributes] = {\n description: \"Element attributes\",\n type: \"array\",\n items: {\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n type: \"object\",\n properties: {\n [propNames.value]: {\n description: \"Attribute value\",\n type: \"string\",\n },\n },\n required: [propNames.value],\n },\n },\n additionalProperties: false,\n },\n };\n\n // If preserving namespaces, add namespace properties to attribute schema\n if (preserveNamespaces) {\n const attrProps =\n elementProperties[propNames.attributes].items.patternProperties[\n \"^.*$\"\n ].properties;\n\n attrProps[propNames.namespace] = {\n description: \"Namespace URI of the attribute\",\n type: \"string\",\n };\n\n attrProps[propNames.prefix] = {\n description: \"Namespace prefix of the attribute\",\n type: \"string\",\n };\n }\n }\n\n // Add CDATA property if preserving CDATA\n if (preserveCDATA) {\n elementProperties[propNames.cdata] = {\n description: \"CDATA section content\",\n type: \"string\",\n };\n }\n\n // Add comments property if preserving comments\n if (preserveComments) {\n elementProperties[propNames.comments] = {\n description: \"Comment content\",\n type: \"string\",\n };\n }\n\n // Add processing instructions property if preserving them\n if (preserveProcessingInstr) {\n elementProperties[propNames.instruction] = {\n description: \"Processing instruction\",\n type: \"object\",\n properties: {\n [propNames.target]: {\n description: \"Processing instruction target\",\n type: \"string\",\n },\n [propNames.value]: {\n description: \"Processing instruction content\",\n type: \"string\",\n },\n },\n required: [propNames.target],\n };\n }\n\n // Add children property with recursive schema\n elementProperties[propNames.children] = {\n description: \"Child elements\",\n type: \"array\",\n items: {\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n $ref: \"#/definitions/element\",\n },\n },\n additionalProperties: false,\n },\n };\n\n // Create element definition (will be referenced recursively)\n const elementDefinition = {\n type: \"object\",\n properties: elementProperties,\n required: requiredProps,\n additionalProperties: false,\n };\n\n // Build the complete schema\n const schema = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n title: \"XJX JSON Schema\",\n description:\n \"Schema for JSON representation of XML documents using the XJX library\",\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n $ref: \"#/definitions/element\",\n },\n },\n additionalProperties: false,\n definitions: {\n element: elementDefinition,\n },\n };\n\n return schema;\n } catch (error) {\n throw new Error(\n `Schema generation failed: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Generate an example JSON object based on the schema\n * @param {string} rootName - Name of the root element\n * @returns {Record} - Example JSON object\n */\n generateExample(rootName: string = \"root\"): Record {\n const propNames = this.config.propNames;\n const preserveNamespaces = this.config.preserveNamespaces;\n const preserveComments = this.config.preserveComments;\n const preserveCDATA = this.config.preserveCDATA;\n const preserveProcessingInstr = this.config.preserveProcessingInstr;\n const preserveAttributes = this.config.preserveAttributes;\n\n // Simple example with common features\n const example: Record = {\n [rootName]: {\n [propNames.value]: \"Root content\",\n [propNames.children]: [\n {\n child: {\n [propNames.value]: \"Child content\",\n },\n },\n ],\n },\n };\n\n // Add namespace properties if enabled\n if (preserveNamespaces) {\n example[rootName][propNames.namespace] = \"http://example.org/ns\";\n example[rootName][propNames.prefix] = \"ex\";\n example[rootName][propNames.children][0].child[propNames.namespace] =\n \"http://example.org/ns\";\n example[rootName][propNames.children][0].child[propNames.prefix] = \"ex\";\n }\n\n // Add attributes if enabled\n if (preserveAttributes) {\n example[rootName][propNames.attributes] = [\n { id: { [propNames.value]: \"root-1\" } },\n { lang: { [propNames.value]: \"en\" } },\n ];\n\n if (preserveNamespaces) {\n example[rootName][propNames.attributes][1].lang[propNames.prefix] =\n \"xml\";\n }\n\n example[rootName][propNames.children][0].child[propNames.attributes] = [\n { id: { [propNames.value]: \"child-1\" } },\n ];\n }\n\n // Add CDATA if enabled\n if (preserveCDATA) {\n example[rootName][propNames.children][0].child[propNames.children] = [\n { [propNames.cdata]: \"Raw content\" },\n ];\n }\n\n // Add comments if enabled\n if (preserveComments) {\n if (!example[rootName][propNames.children][0].child[propNames.children]) {\n example[rootName][propNames.children][0].child[propNames.children] = [];\n }\n\n example[rootName][propNames.children][0].child[propNames.children].push({\n [propNames.comments]: \"Comment about the child\",\n });\n }\n\n // Add processing instruction if enabled\n if (preserveProcessingInstr) {\n if (!example[rootName][propNames.children]) {\n example[rootName][propNames.children] = [];\n }\n\n example[rootName][propNames.children].unshift({\n [propNames.instruction]: {\n [propNames.target]: \"xml-stylesheet\",\n [propNames.value]: 'type=\"text/css\" href=\"style.css\"',\n },\n });\n }\n\n return example;\n }\n}\n","/**\n * Utilities for applying value transformations\n */\nimport { Configuration } from '../types/types';\nimport { TransformContext, TransformDirection } from './ValueTransformer';\nimport { DOMAdapter } from '../DOMAdapter';\n\n/**\n * Utility for applying value transformations\n */\nexport class TransformUtil {\n private config: Configuration;\n\n /**\n * Create a new TransformUtil\n * @param config Configuration\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Apply transforms to a value\n * @param value Value to transform\n * @param context Transformation context\n * @returns Transformed value\n */\n applyTransforms(value: any, context: TransformContext): any {\n // Skip transformation if no transformers are configured\n if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) {\n return value;\n }\n\n // Apply each transformer in sequence\n let transformedValue = value;\n for (const transformer of this.config.valueTransforms) {\n transformedValue = transformer.process(transformedValue, context);\n }\n\n return transformedValue;\n }\n\n /**\n * Create a transform context\n * @param direction Direction of transformation\n * @param nodeName Name of the current node\n * @param nodeType DOM node type\n * @param options Additional context options\n * @returns Transform context\n */\n createContext(\n direction: TransformDirection,\n nodeName: string,\n nodeType: number,\n options: {\n path?: string;\n namespace?: string;\n prefix?: string;\n isAttribute?: boolean;\n attributeName?: string;\n parent?: TransformContext;\n } = {}\n ): TransformContext {\n return {\n direction,\n nodeName,\n nodeType,\n path: options.path || nodeName,\n namespace: options.namespace,\n prefix: options.prefix,\n isAttribute: options.isAttribute || false,\n attributeName: options.attributeName,\n parent: options.parent,\n config: this.config,\n };\n }\n\n /**\n * Get a user-friendly node type name for debugging\n * @param nodeType DOM node type\n * @returns String representation of node type\n */\n getNodeTypeName(nodeType: number): string {\n return DOMAdapter.getNodeTypeName(nodeType);\n }\n}","/**\n * XMLToJSON class for converting XML to JSON with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { JSONUtil } from \"./utils/JsonUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * XMLToJSON Parser for converting XML to JSON\n */\nexport class XMLToJSON {\n private config: Configuration;\n private jsonUtil: JSONUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for XMLToJSON\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.jsonUtil = new JSONUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public parse(xmlString: string): Record {\n try {\n const xmlDoc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n // Check for parsing errors\n const errors = xmlDoc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n throw new XJXError(`XML parsing error: ${errors[0].textContent}`);\n }\n\n return this.nodeToJson(xmlDoc.documentElement);\n } catch (error) {\n throw new XJXError(\n `Failed to convert XML to JSON: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert a DOM node to JSON representation\n * @param node DOM node to convert\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the XML tree\n * @returns JSON representation of the node\n */\n private nodeToJson(node: Node, parentContext?: TransformContext, path: string = \"\"): Record {\n const result: Record = {};\n\n // Handle element nodes\n if (node.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n const element = node as Element;\n // Use localName instead of nodeName to strip namespace prefix\n const nodeName =\n element.localName ||\n element.nodeName.split(\":\").pop() ||\n element.nodeName;\n\n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n const nodeObj: Record = {};\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: currentPath,\n namespace: element.namespaceURI || undefined,\n prefix: element.prefix || undefined,\n parent: parentContext\n }\n );\n\n // Process namespaces if enabled\n if (this.config.preserveNamespaces) {\n const ns = element.namespaceURI;\n if (ns) {\n nodeObj[this.config.propNames.namespace] = ns;\n }\n\n const prefix = element.prefix;\n if (prefix) {\n nodeObj[this.config.propNames.prefix] = prefix;\n }\n }\n\n // Process attributes if enabled\n if (this.config.preserveAttributes && element.attributes.length > 0) {\n const attrs: Array> = [];\n\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n // Strip namespace prefix from attribute name\n const attrLocalName =\n attr.localName || attr.name.split(\":\").pop() || attr.name;\n\n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: `${currentPath}.${attrLocalName}`,\n namespace: attr.namespaceURI || undefined,\n prefix: attr.prefix || undefined,\n isAttribute: true,\n attributeName: attrLocalName,\n parent: context\n }\n );\n\n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attr.value,\n attrContext\n );\n\n // Create attribute object with consistent structure\n const attrObj: Record = {\n [attrLocalName]: {\n [this.config.propNames.value]: transformedValue,\n },\n };\n\n // Add namespace info for attribute if present and enabled\n if (this.config.preserveNamespaces) {\n // Handle attribute namespace\n if (attr.namespaceURI) {\n attrObj[attrLocalName][this.config.propNames.namespace] =\n attr.namespaceURI;\n }\n\n // Handle attribute prefix\n if (attr.prefix) {\n attrObj[attrLocalName][this.config.propNames.prefix] =\n attr.prefix;\n }\n }\n\n attrs.push(attrObj);\n }\n\n if (attrs.length > 0) {\n nodeObj[this.config.propNames.attributes] = attrs;\n }\n }\n\n // Process child nodes\n if (element.childNodes.length > 0) {\n const children: Array> = [];\n const childrenKey = this.config.propNames.children;\n const valueKey = this.config.propNames.value;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n\n // Text nodes - only process if preserveTextNodes is true\n if (child.nodeType === DOMAdapter.nodeTypes.TEXT_NODE) {\n if (this.config.preserveTextNodes) {\n let text = child.nodeValue || \"\";\n\n // Skip whitespace-only text nodes if whitespace preservation is disabled\n if (!this.config.preserveWhitespace) {\n if (text.trim() === \"\") {\n continue;\n }\n // Trim the text when preserveWhitespace is false\n text = text.trim();\n }\n\n // Create text node context\n const textContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#text',\n child.nodeType,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n\n // Apply transformations to text value\n const transformedText = this.transformUtil.applyTransforms(\n text,\n textContext\n );\n\n children.push({ [valueKey]: transformedText });\n }\n }\n // CDATA sections\n else if (\n child.nodeType === DOMAdapter.nodeTypes.CDATA_SECTION_NODE &&\n this.config.preserveCDATA\n ) {\n // Create CDATA context\n const cdataContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#cdata',\n child.nodeType,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n\n // Apply transformations to CDATA value\n const transformedCData = this.transformUtil.applyTransforms(\n child.nodeValue || \"\",\n cdataContext\n );\n\n children.push({\n [cdataKey]: transformedCData,\n });\n }\n // Comments\n else if (\n child.nodeType === DOMAdapter.nodeTypes.COMMENT_NODE &&\n this.config.preserveComments\n ) {\n children.push({\n [commentsKey]: child.nodeValue || \"\",\n });\n }\n // Processing instructions\n else if (\n child.nodeType ===\n DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE &&\n this.config.preserveProcessingInstr\n ) {\n children.push({\n [instructionKey]: {\n [targetKey]: child.nodeName,\n [valueKey]: child.nodeValue || \"\",\n },\n });\n }\n // Element nodes (recursive)\n else if (child.nodeType === DOMAdapter.nodeTypes.ELEMENT_NODE) {\n children.push(this.nodeToJson(child, context, currentPath));\n }\n }\n\n if (children.length > 0) {\n nodeObj[childrenKey] = children;\n }\n }\n\n // Apply compact option - remove empty properties if enabled\n if (this.config.outputOptions.compact) {\n Object.keys(nodeObj).forEach((key) => {\n const cleaned = this.cleanNode(nodeObj[key]);\n if (cleaned === undefined) {\n delete nodeObj[key];\n } else {\n nodeObj[key] = cleaned;\n }\n });\n }\n\n result[nodeName] = nodeObj;\n }\n\n return result;\n }\n\n private cleanNode(node: any): any {\n if (Array.isArray(node)) {\n // Clean each item in the array and filter out empty ones\n const cleanedArray = node\n .map((item) => this.cleanNode(item))\n .filter((item) => {\n return !(\n item === null ||\n item === undefined ||\n (typeof item === \"object\" && Object.keys(item).length === 0)\n );\n });\n return cleanedArray.length > 0 ? cleanedArray : undefined;\n } else if (typeof node === \"object\" && node !== null) {\n // Clean properties recursively\n Object.keys(node).forEach((key) => {\n const cleanedChild = this.cleanNode(node[key]);\n if (\n cleanedChild === null ||\n cleanedChild === undefined ||\n (Array.isArray(cleanedChild) && cleanedChild.length === 0) ||\n (typeof cleanedChild === \"object\" &&\n Object.keys(cleanedChild).length === 0)\n ) {\n delete node[key];\n } else {\n node[key] = cleanedChild;\n }\n });\n\n // Handle the special case for nodes with only empty children/attributes\n const childrenKey = this.config.propNames.children;\n const attrsKey = this.config.propNames.attributes;\n const keys = Object.keys(node);\n if (\n keys.every((key) => key === childrenKey || key === attrsKey) &&\n (node[childrenKey] === undefined ||\n this.jsonUtil.isEmpty(node[childrenKey])) &&\n (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))\n ) {\n return undefined;\n }\n\n return Object.keys(node).length > 0 ? node : undefined;\n }\n\n return node;\n }\n}","/**\n * XMLUtil - Utility functions for XML processing\n */\nimport { XJXError } from \"../types/errors\";\nimport { DOMAdapter } from \"../DOMAdapter\";\nimport { Configuration } from \"../types/types\";\n\nexport class XMLUtil {\n private config: Configuration;\n\n /**\n * Constructor for XMLUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n prettyPrintXml(xmlString: string): string {\n const indent = this.config.outputOptions.indent;\n const INDENT = \" \".repeat(indent);\n\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n const serializer = (node: Node, level = 0): string => {\n const pad = INDENT.repeat(level);\n\n switch (node.nodeType) {\n case DOMAdapter.nodeTypes.ELEMENT_NODE: {\n const el = node as Element;\n const tagName = el.tagName;\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`;\n\n const children = Array.from(el.childNodes);\n\n if (children.length === 0) {\n return `${pad}${openTag.replace(/>$/, \" />\")}\\n`;\n }\n\n // Single text node: print inline\n if (\n children.length === 0 ||\n (children.length === 1 &&\n children[0].nodeType === DOMAdapter.nodeTypes.TEXT_NODE &&\n children[0].textContent?.trim() === \"\")\n ) {\n // Empty or whitespace-only\n return `${pad}<${tagName}${attrs ? \" \" + attrs : \"\"}>\\n`;\n }\n\n const inner = children\n .map((child) => serializer(child, level + 1))\n .join(\"\");\n return `${pad}${openTag}\\n${inner}${pad}\\n`;\n }\n\n case DOMAdapter.nodeTypes.TEXT_NODE: {\n const text = node.textContent?.trim();\n return text ? `${pad}${text}\\n` : \"\";\n }\n\n case DOMAdapter.nodeTypes.CDATA_SECTION_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.COMMENT_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.PROCESSING_INSTRUCTION_NODE:\n const pi = node as ProcessingInstruction;\n return `${pad}\\n`;\n\n case DOMAdapter.nodeTypes.DOCUMENT_NODE:\n return Array.from(node.childNodes)\n .map((child) => serializer(child, level))\n .join(\"\");\n\n default:\n return \"\";\n }\n };\n\n return serializer(doc).trim();\n } catch (error) {\n throw new XJXError(\n `Failed to pretty print XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Check if XML string is well-formed\n * @param xmlString XML string to validate\n * @returns Object with validation result and any error messages\n */\n validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n const errors = doc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n return {\n isValid: false,\n message: errors[0].textContent || \"Unknown parsing error\",\n };\n }\n return { isValid: true };\n } catch (error) {\n return {\n isValid: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Add XML declaration to a string if missing\n * @param xmlString XML string\n * @returns XML string with declaration\n */\n ensureXMLDeclaration(xmlString: string): string {\n if (!xmlString.trim().startsWith(\"\\n' + xmlString;\n }\n return xmlString;\n }\n\n /**\n * Escapes special characters in text for safe XML usage.\n * @param text Text to escape.\n * @returns Escaped XML string.\n */\n escapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&\";\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case '\"':\n return \""\";\n case \"'\":\n return \"'\";\n default:\n return char;\n }\n });\n }\n\n /**\n * Unescapes XML entities back to their character equivalents.\n * @param text Text with XML entities.\n * @returns Unescaped text.\n */\n unescapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => {\n switch (entity) {\n case \"amp\":\n return \"&\";\n case \"lt\":\n return \"<\";\n case \"gt\":\n return \">\";\n case \"quot\":\n return '\"';\n case \"apos\":\n return \"'\";\n default:\n return match;\n }\n });\n }\n\n /**\n * Extract the namespace prefix from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Prefix or null if no prefix\n */\n extractPrefix(qualifiedName: string): string | null {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null;\n }\n\n /**\n * Extract the local name from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Local name\n */\n extractLocalName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0\n ? qualifiedName.substring(colonIndex + 1)\n : qualifiedName;\n }\n\n /**\n * Create a qualified name from prefix and local name\n * @param prefix Namespace prefix (can be null)\n * @param localName Local name\n * @returns Qualified name\n */\n createQualifiedName(prefix: string | null, localName: string): string {\n return prefix ? `${prefix}:${localName}` : localName;\n }\n}","/**\n * JSONToXML class for converting JSON to XML with consistent namespace handling\n */\nimport { Configuration } from \"./types/types\";\nimport { XJXError } from \"./types/errors\";\nimport { DOMAdapter } from \"./DOMAdapter\";\nimport { XMLUtil } from \"./utils/XmlUtils\";\nimport { TransformUtil } from \"./transforms/TransformUtil\";\nimport { TransformContext } from \"./transforms/ValueTransformer\";\n\n/**\n * JSONToXML for converting JSON to XML\n */\nexport class JSONToXML {\n private config: Configuration;\n private xmlUtil: XMLUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for JSONToXML\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.xmlUtil = new XMLUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert JSON object to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public serialize(jsonObj: Record): string {\n try {\n const doc = DOMAdapter.createDocument();\n const rootElement = this.jsonToNode(jsonObj, doc);\n\n if (rootElement) {\n // Handle the temporary root element if it exists\n if (doc.documentElement && doc.documentElement.nodeName === \"temp\") {\n doc.replaceChild(rootElement, doc.documentElement);\n } else {\n doc.appendChild(rootElement);\n }\n }\n\n // Add XML declaration if specified\n let xmlString = DOMAdapter.serializeToString(doc);\n\n // remove xhtml decl inserted by dom\n xmlString = xmlString.replace(' xmlns=\"http://www.w3.org/1999/xhtml\"', '');\n\n if (this.config.outputOptions.xml.declaration) {\n xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString);\n }\n\n // Apply pretty printing if enabled\n if (this.config.outputOptions.prettyPrint) {\n xmlString = this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n return xmlString;\n } catch (error) {\n throw new XJXError(\n `Failed to convert JSON to XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert JSON object to DOM node\n * @param jsonObj JSON object to convert\n * @param doc Document for creating elements\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the JSON object\n * @returns DOM Element\n */\n private jsonToNode(\n jsonObj: Record,\n doc: Document,\n parentContext?: TransformContext,\n path: string = \"\"\n ): Element | null {\n if (!jsonObj || typeof jsonObj !== \"object\") {\n return null;\n }\n\n // Get the node name (first key in the object)\n const nodeName = Object.keys(jsonObj)[0];\n if (!nodeName) {\n return null;\n }\n\n const nodeData = jsonObj[nodeName];\n \n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n // Create element with namespace if available\n let element: Element;\n const namespaceKey = this.config.propNames.namespace;\n const prefixKey = this.config.propNames.prefix;\n const ns = nodeData[namespaceKey];\n const prefix = nodeData[prefixKey];\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: currentPath,\n namespace: ns,\n prefix: prefix,\n parent: parentContext\n }\n );\n\n if (ns && this.config.preserveNamespaces) {\n if (prefix) {\n // Create element with namespace and prefix\n element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`);\n } else {\n // Create element with namespace but no prefix\n element = DOMAdapter.createElementNS(ns, nodeName);\n }\n } else {\n // Create element without namespace\n element = DOMAdapter.createElement(nodeName);\n }\n\n // Process attributes if enabled\n const attributesKey = this.config.propNames.attributes;\n const valueKey = this.config.propNames.value;\n if (\n this.config.preserveAttributes &&\n nodeData[attributesKey] &&\n Array.isArray(nodeData[attributesKey])\n ) {\n nodeData[attributesKey].forEach(\n (attrObj: Record) => {\n const attrName = Object.keys(attrObj)[0];\n if (!attrName) return;\n\n const attrData = attrObj[attrName];\n \n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.ELEMENT_NODE,\n {\n path: `${currentPath}.${attrName}`,\n namespace: attrData[namespaceKey],\n prefix: attrData[prefixKey],\n isAttribute: true,\n attributeName: attrName,\n parent: context\n }\n );\n \n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attrData[valueKey] || \"\",\n attrContext\n );\n \n const attrNs = attrData[namespaceKey];\n const attrPrefix = attrData[prefixKey];\n\n // Form qualified name for attribute if it has a prefix\n let qualifiedName = attrName;\n if (attrPrefix && this.config.preserveNamespaces) {\n qualifiedName = `${attrPrefix}:${attrName}`;\n }\n\n DOMAdapter.setNamespacedAttribute(\n element, \n (attrNs && this.config.preserveNamespaces) ? attrNs : null, \n qualifiedName, \n transformedValue\n );\n }\n );\n }\n\n // Process simple text value\n if (nodeData[valueKey] !== undefined) {\n // Apply transformations to text value\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n namespace: ns,\n prefix: prefix,\n parent: context\n }\n );\n \n const transformedValue = this.transformUtil.applyTransforms(\n nodeData[valueKey],\n textContext\n );\n \n element.textContent = transformedValue;\n }\n\n // Process children\n const childrenKey = this.config.propNames.children;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n if (\n nodeData[childrenKey] &&\n Array.isArray(nodeData[childrenKey])\n ) {\n nodeData[childrenKey].forEach(\n (child: Record) => {\n // Text nodes\n if (\n child[valueKey] !== undefined &&\n this.config.preserveTextNodes\n ) {\n // Apply transformations to text node\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#text',\n DOMAdapter.nodeTypes.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n \n const transformedText = this.transformUtil.applyTransforms(\n child[valueKey],\n textContext\n );\n \n element.appendChild(\n DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))\n );\n }\n // CDATA sections\n else if (\n child[cdataKey] !== undefined &&\n this.config.preserveCDATA\n ) {\n // Apply transformations to CDATA\n const cdataContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#cdata',\n DOMAdapter.nodeTypes.CDATA_SECTION_NODE,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n \n const transformedCData = this.transformUtil.applyTransforms(\n child[cdataKey],\n cdataContext\n );\n \n element.appendChild(\n DOMAdapter.createCDATASection(\n transformedCData\n )\n );\n }\n // Comments\n else if (\n child[commentsKey] !== undefined &&\n this.config.preserveComments\n ) {\n element.appendChild(\n DOMAdapter.createComment(\n child[commentsKey]\n )\n );\n }\n // Processing instructions\n else if (\n child[instructionKey] !== undefined &&\n this.config.preserveProcessingInstr\n ) {\n const piData = child[instructionKey];\n const target = piData[targetKey];\n const data = piData[valueKey] || \"\";\n\n if (target) {\n element.appendChild(\n DOMAdapter.createProcessingInstruction(target, data)\n );\n }\n }\n // Element nodes (recursive)\n else {\n const childElement = this.jsonToNode(child, doc, context, currentPath);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n }\n );\n }\n\n return element;\n }\n}","/**\n * Default configuration for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: Configuration = {\n preserveNamespaces: true,\n preserveComments: true,\n preserveProcessingInstr: true,\n preserveCDATA: true,\n preserveTextNodes: true,\n preserveWhitespace: false,\n preserveAttributes: true,\n\n outputOptions: {\n prettyPrint: true,\n indent: 2,\n compact: true,\n json: {},\n xml: {\n declaration: true,\n },\n },\n\n propNames: {\n namespace: \"$ns\",\n prefix: \"$pre\",\n attributes: \"$attr\",\n value: \"$val\",\n cdata: \"$cdata\",\n comments: \"$cmnt\",\n instruction: \"$pi\", \n target: \"$trgt\", \n children: \"$children\",\n },\n};","/**\n * XJX - Facade class for XML-JSON conversion operations\n */\nimport { XMLToJSON } from \"./core/XmlToJsonConverter\";\nimport { JSONToXML } from \"./core/JsonToXmlConverter\";\nimport { Configuration } from \"./core/types/types\";\nimport { DEFAULT_CONFIG } from \"./core/config/config\";\nimport { DOMAdapter } from \"./core/DOMAdapter\";\nimport { XMLUtil } from \"./core/utils/XmlUtils\";\nimport { JSONUtil } from \"./core/utils/JsonUtils\";\nimport { ValueTransformer } from \"./core/transforms\";\n\nexport class XJX {\n private config: Configuration;\n private xmltojson: XMLToJSON;\n private jsontoxml: JSONToXML;\n private jsonUtil: JSONUtil;\n private xmlUtil: XMLUtil;\n\n /**\n * Constructor for XJX utility\n * @param config Configuration options\n */\n constructor(config: Partial = {}) {\n // First create a jsonUtil instance with default config to use its methods\n this.jsonUtil = new JSONUtil(DEFAULT_CONFIG);\n\n // Create a deep clone of the default config\n const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG);\n\n // Deep merge with the provided config\n this.config = this.jsonUtil.deepMerge(defaultClone, config);\n\n // Re-initialize jsonUtil with the merged config\n this.jsonUtil = new JSONUtil(this.config);\n\n // Initialize other components\n this.xmlUtil = new XMLUtil(this.config);\n this.xmltojson = new XMLToJSON(this.config);\n this.jsontoxml = new JSONToXML(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public xmlToJson(xmlString: string): Record {\n return this.xmltojson.parse(xmlString);\n }\n\n /**\n * Convert JSON object back to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public jsonToXml(jsonObj: Record): string {\n return this.jsontoxml.serialize(jsonObj);\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n public prettyPrintXml(xmlString: string): string {\n return this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns The value at the specified path or the fallback value\n */\n public getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n return this.jsonUtil.getPath(obj, path, fallback);\n }\n\n /**\n * Validate XML string\n * @param xmlString XML string to validate\n * @returns Validation result\n */\n public validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n return this.xmlUtil.validateXML(xmlString);\n }\n\n /**\n * Generate a JSON schema based on the current configuration\n * @returns JSON schema object for validating XML-JSON documents\n */\n public generateJsonSchema(): Record {\n return this.jsonUtil.generateJsonSchema();\n }\n\n /**\n * Convert a standard JSON object to the XML-like JSON structure\n * @param obj Standard JSON object\n * @param root Optional root element configuration (string or object with properties)\n * @returns XML-like JSON object ready for conversion to XML\n */\n public objectToXJX(obj: any, root?: string | Record): Record {\n return this.jsonUtil.objectToXJX(obj, root);\n }\n\n /**\n * Generate an example JSON object that matches the current configuration\n * @param rootName Name of the root element\n * @returns Example JSON object\n */\n public generateJsonExample(rootName: string = \"root\"): Record {\n return this.jsonUtil.generateExample(rootName);\n }\n\n /**\n * Add a value transformer to the configuration\n * @param transformer Value transformer to add\n * @returns This XJX instance for chaining\n */\n public addTransformer(transformer: ValueTransformer): XJX {\n if (!this.config.valueTransforms) {\n this.config.valueTransforms = [];\n }\n this.config.valueTransforms.push(transformer);\n return this;\n }\n\n /**\n * Removes all value transformers from the configuration\n * @returns This XJX instance for chaining\n */\n public clearTransformers(): XJX {\n this.config.valueTransforms = [];\n return this;\n }\n\n /**\n * Clean up any resources\n */\n public cleanup(): void {\n DOMAdapter.cleanup();\n }\n}","/**\n * Value transformation types and base class for the XJX library\n */\nimport { Configuration } from '../types/types';\n\n/**\n * Direction of the transformation\n */\nexport type TransformDirection = 'xml-to-json' | 'json-to-xml';\n\n/**\n * Context provided to value transformers\n */\nexport interface TransformContext {\n // Core transformation info\n direction: TransformDirection; // Direction of the current transformation\n \n // Node information\n nodeName: string; // Name of the current node\n nodeType: number; // DOM node type (element, text, etc.)\n namespace?: string; // Namespace URI if available\n prefix?: string; // Namespace prefix if available\n \n // Structure information\n path: string; // Dot-notation path to current node\n isAttribute: boolean; // Whether the current value is from an attribute\n attributeName?: string; // Name of attribute if isAttribute is true\n \n // Parent context (creates a chain)\n parent?: TransformContext; // Reference to parent context for traversal\n \n // Configuration reference\n config: Configuration; // Reference to the current configuration\n}\n\n/**\n * Abstract base class for value transformers\n */\nexport abstract class ValueTransformer {\n /**\n * Process a value, transforming it if applicable\n * @param value Value to potentially transform\n * @param context Context including direction and other information\n * @returns Transformed value or original if not applicable\n */\n process(value: any, context: TransformContext): any {\n if (context.direction === 'xml-to-json') {\n return this.xmlToJson(value, context);\n } else {\n return this.jsonToXml(value, context);\n }\n }\n\n /**\n * Transform a value from XML to JSON representation\n * @param value Value from XML\n * @param context Transformation context\n * @returns Transformed value for JSON\n */\n protected xmlToJson(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n\n /**\n * Transform a value from JSON to XML representation\n * @param value Value from JSON\n * @param context Transformation context\n * @returns Transformed value for XML\n */\n protected jsonToXml(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n}","// Import locally so you can use it below\nimport { XJX } from './XJX';\n\n// Core components\nexport { XJX };\nexport { Configuration } from './core/types/types';\nexport { DEFAULT_CONFIG } from './core/config/config';\n\n// Error handling\nexport { XJXError } from './core/types/errors';\n\n// Allow custom transformers\nexport { ValueTransformer } from './core/transforms/ValueTransformer';\n\n// Default export\nexport default XJX;"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["../../src/core/types/error-types.ts","../../src/core/types/dom-types.ts","../../src/core/adapters/dom-adapter.ts","../../src/core/utils/json-utils.ts","../../src/core/transformers/TransformUtil.ts","../../src/core/converters/xml-to-json-converter.ts","../../src/core/utils/xml-utils.ts","../../src/core/converters/json-to-xml-converter.ts","../../src/core/config/config.ts","../../src/XJX.ts","../../src/core/transformers/ValueTransformer.ts","../../src/index.ts"],"sourcesContent":["/**\n * Error classes for the XJX library\n */\n\n/**\n * Base error class\n */\nexport class XJXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'XMLToJSONError';\n }\n}\n\n/**\n * Error for XML parsing issues\n */\nexport class XmlToJsonError extends XJXError {\n constructor(message: string) {\n super(`XML parse error: ${message}`);\n this.name = 'XmlToJsonError';\n }\n}\n\n/**\n * Error for XML serialization issues\n */\nexport class JsonToXmlError extends XJXError {\n constructor(message: string) {\n super(`XML serialization error: ${message}`);\n this.name = 'JsonToXmlError';\n }\n}\n\n/**\n * Error for environment incompatibility\n */\nexport class EnvironmentError extends XJXError {\n constructor(message: string) {\n super(`Environment error: ${message}`);\n this.name = 'EnvironmentError';\n }\n}\n\n/**\n * Error for invalid configuration\n */\nexport class ConfigurationError extends XJXError {\n constructor(message: string) {\n super(`Configuration error: ${message}`);\n this.name = 'ConfigurationError';\n }\n}","/**\n * DOM node types as an enum for better type safety\n */\nexport enum NodeType {\n ELEMENT_NODE = 1,\n ATTRIBUTE_NODE = 2,\n TEXT_NODE = 3, \n CDATA_SECTION_NODE = 4,\n PROCESSING_INSTRUCTION_NODE = 7,\n COMMENT_NODE = 8,\n DOCUMENT_NODE = 9\n }","/**\n * DOM Environment provider with unified interface for browser and Node.js\n */\nimport { XJXError } from '../types/error-types';\nimport { NodeType } from '../types/dom-types';\n\n\ninterface DOMWindow {\n DOMParser: any;\n XMLSerializer: any;\n // Node: {\n // ELEMENT_NODE: number;\n // TEXT_NODE: number;\n // CDATA_SECTION_NODE: number;\n // COMMENT_NODE: number;\n // PROCESSING_INSTRUCTION_NODE: number;\n // DOCUMENT_NODE: number; \n // };\n document: Document;\n close?: () => void; \n}\n\ninterface JSDOMInstance {\n window: DOMWindow;\n}\n\nexport const DOMAdapter = (() => {\n // Environment-specific DOM implementation\n let domParser: any;\n let xmlSerializer: any;\n // let nodeTypes: NodeTypes;\n let docImplementation: any;\n let jsdomInstance: JSDOMInstance | null = null;\n\n try {\n if (typeof window === \"undefined\") {\n // Node.js environment - try JSDOM first\n try {\n const { JSDOM } = require(\"jsdom\");\n jsdomInstance = new JSDOM(\"\", {\n contentType: \"text/xml\",\n }) as JSDOMInstance;\n\n domParser = jsdomInstance.window.DOMParser;\n xmlSerializer = jsdomInstance.window.XMLSerializer;\n // nodeTypes = {\n // ELEMENT_NODE: jsdomInstance.window.Node.ELEMENT_NODE,\n // TEXT_NODE: jsdomInstance.window.Node.TEXT_NODE,\n // CDATA_SECTION_NODE: jsdomInstance.window.Node.CDATA_SECTION_NODE,\n // COMMENT_NODE: jsdomInstance.window.Node.COMMENT_NODE,\n // PROCESSING_INSTRUCTION_NODE: jsdomInstance.window.Node.PROCESSING_INSTRUCTION_NODE,\n // DOCUMENT_NODE: jsdomInstance.window.Node.DOCUMENT_NODE, // Add this line\n // };\n docImplementation = jsdomInstance.window.document.implementation;\n } catch (jsdomError) {\n // Fall back to xmldom if JSDOM isn't available\n try {\n const { DOMParser, XMLSerializer, DOMImplementation } = require('@xmldom/xmldom');\n domParser = DOMParser;\n xmlSerializer = XMLSerializer;\n // Standard DOM node types\n // nodeTypes = {\n // ELEMENT_NODE: 1,\n // TEXT_NODE: 3,\n // CDATA_SECTION_NODE: 4,\n // COMMENT_NODE: 8,\n // PROCESSING_INSTRUCTION_NODE: 7,\n // DOCUMENT_NODE: 9, \n // };\n const implementation = new DOMImplementation();\n docImplementation = implementation;\n } catch (xmldomError) {\n throw new XJXError(`Node.js environment detected but neither 'jsdom' nor '@xmldom/xmldom' are available.`);\n }\n }\n } else {\n // Browser environment\n if (!window.DOMParser) {\n throw new XJXError(\"DOMParser is not available in this environment\");\n }\n\n if (!window.XMLSerializer) {\n throw new XJXError(\"XMLSerializer is not available in this environment\");\n }\n\n domParser = window.DOMParser;\n xmlSerializer = window.XMLSerializer;\n // nodeTypes = {\n // ELEMENT_NODE: Node.ELEMENT_NODE,\n // TEXT_NODE: Node.TEXT_NODE,\n // CDATA_SECTION_NODE: Node.CDATA_SECTION_NODE,\n // COMMENT_NODE: Node.COMMENT_NODE,\n // PROCESSING_INSTRUCTION_NODE: Node.PROCESSING_INSTRUCTION_NODE,\n // DOCUMENT_NODE: Node.DOCUMENT_NODE, \n // };\n docImplementation = document.implementation;\n }\n } catch (error) {\n throw new XJXError(`DOM environment initialization failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n return {\n createParser: () => {\n try {\n return new domParser();\n } catch (error) {\n throw new XJXError(`Failed to create DOM parser: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createSerializer: () => {\n try {\n return new xmlSerializer();\n } catch (error) {\n throw new XJXError(`Failed to create XML serializer: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n NodeType,\n \n parseFromString: (xmlString: string, contentType: string = 'text/xml') => {\n try {\n const parser = new domParser();\n return parser.parseFromString(xmlString, contentType);\n } catch (error) {\n throw new XJXError(`Failed to parse XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n serializeToString: (node: Node) => {\n try {\n const serializer = new xmlSerializer();\n return serializer.serializeToString(node);\n } catch (error) {\n throw new XJXError(`Failed to serialize XML: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createDocument: () => {\n try {\n // For browsers, create a document with a root element to avoid issues\n if (typeof window !== \"undefined\") {\n const parser = new domParser();\n return parser.parseFromString('', 'text/xml');\n } else {\n return docImplementation.createDocument(null, null, null);\n }\n } catch (error) {\n throw new XJXError(`Failed to create document: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElement: (tagName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElement(tagName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElement(tagName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createElementNS: (namespaceURI: string, qualifiedName: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createElementNS(namespaceURI, qualifiedName);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createElementNS(namespaceURI, qualifiedName);\n }\n } catch (error) {\n throw new XJXError(`Failed to create element with namespace: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createTextNode: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createTextNode(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createTextNode(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create text node: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createCDATASection: (data: string) => {\n try {\n // For browser compatibility, use document.implementation to create CDATA\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createCDATASection(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create CDATA section: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createComment: (data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n return document.createComment(data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createComment(data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create comment: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n createProcessingInstruction: (target: string, data: string) => {\n try {\n if (typeof window !== \"undefined\") {\n const doc = document.implementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n } else {\n const doc = docImplementation.createDocument(null, null, null);\n return doc.createProcessingInstruction(target, data);\n }\n } catch (error) {\n throw new XJXError(`Failed to create processing instruction: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n // New helper methods\n \n /**\n * Creates a proper namespace qualified attribute\n */\n setNamespacedAttribute: (element: Element, namespaceURI: string | null, qualifiedName: string, value: string): void => {\n try {\n if (namespaceURI) {\n element.setAttributeNS(namespaceURI, qualifiedName, value);\n } else {\n element.setAttribute(qualifiedName, value);\n }\n } catch (error) {\n throw new XJXError(`Failed to set attribute: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n \n /**\n * Check if an object is a DOM node\n */\n isNode: (obj: any): boolean => {\n try {\n return obj && typeof obj === 'object' && typeof obj.nodeType === 'number';\n } catch (error) {\n return false;\n }\n },\n \n /**\n * Get DOM node type as string for debugging\n */\n getNodeTypeName: (nodeType: number): string => {\n switch (nodeType) {\n case NodeType.ELEMENT_NODE: return 'ELEMENT_NODE';\n case NodeType.TEXT_NODE: return 'TEXT_NODE';\n case NodeType.CDATA_SECTION_NODE: return 'CDATA_SECTION_NODE';\n case NodeType.COMMENT_NODE: return 'COMMENT_NODE';\n case NodeType.PROCESSING_INSTRUCTION_NODE: return 'PROCESSING_INSTRUCTION_NODE';\n default: return `UNKNOWN_NODE_TYPE(${nodeType})`;\n }\n },\n \n /**\n * Get all node attributes as an object\n */\n getNodeAttributes: (node: Element): Record => {\n const result: Record = {};\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n result[attr.name] = attr.value;\n }\n return result;\n },\n \n // Cleanup method (mainly for JSDOM)\n cleanup: () => {\n if (jsdomInstance && typeof jsdomInstance.window.close === 'function') {\n jsdomInstance.window.close();\n }\n }\n };\n})();","/**\n * JSONUtil - Utility functions for JSON processing\n */\nimport { Configuration } from \"../types/config-types\";\nimport { JSONValue } from \"../types/json-types\";\n\nexport class JsonUtil {\n private config: Configuration;\n\n /**\n * Constructor for JSONUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * Automatically traverses into children arrays and flattens results.\n *\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns Retrieved value or fallback\n */\n getPath(\n obj: Record,\n path: string,\n fallback?: JSONValue\n ): any {\n const segments = path.split(\".\");\n let current: any = obj;\n\n for (const segment of segments) {\n if (Array.isArray(current)) {\n // Apply the segment to each array element and flatten results\n const results = current\n .map((item) => this.resolveSegment(item, segment))\n .flat()\n .filter((v) => v !== undefined);\n current = results.length > 0 ? results : undefined;\n } else {\n current = this.resolveSegment(current, segment);\n }\n\n if (current === undefined) return fallback;\n }\n\n // Collapse singleton arrays\n if (Array.isArray(current) && current.length === 1) {\n return current[0];\n }\n\n return current !== undefined ? current : fallback;\n }\n\n /**\n * Resolves a single path segment in the context of a JSON object.\n * Falls back to searching children for matching keys.\n *\n * @param obj The current object\n * @param segment The path segment to resolve\n * @returns Resolved value or undefined\n */\n private resolveSegment(obj: any, segment: string): any {\n if (obj == null || typeof obj !== \"object\") return undefined;\n\n // Direct property access\n if (segment in obj) {\n return obj[segment];\n }\n\n // Check if this is a special property name that matches the config\n if (\n segment === this.config.propNames.value ||\n segment === this.config.propNames.children ||\n segment === this.config.propNames.attributes ||\n segment === this.config.propNames.namespace ||\n segment === this.config.propNames.prefix ||\n segment === this.config.propNames.cdata ||\n segment === this.config.propNames.comments ||\n segment === this.config.propNames.instruction ||\n segment === this.config.propNames.target\n ) {\n const configKey = Object.entries(this.config.propNames).find(\n ([_, value]) => value === segment\n )?.[0];\n\n if (configKey && obj[segment] !== undefined) {\n return obj[segment];\n }\n }\n\n // Check children for objects that contain the segment\n const childrenKey = this.config.propNames.children;\n const children = obj[childrenKey];\n if (Array.isArray(children)) {\n const matches = children\n .map((child) => (segment in child ? child[segment] : undefined))\n .filter((v) => v !== undefined);\n return matches.length > 0 ? matches : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Converts a plain JSON object to the XML-like JSON structure.\n * Optionally wraps the result in a root element with attributes and namespaces.\n *\n * @param obj Standard JSON object\n * @param root Optional root element configuration (either a string or object with $ keys)\n * @returns XML-like JSON object\n */\n objectToXJX(obj: any, root?: any): any {\n const wrappedObject = this.wrapObject(obj);\n\n if (typeof root === \"string\") {\n // Root is a simple string: wrap result with this root tag\n return { [root]: wrappedObject };\n }\n\n if (root && typeof root === \"object\") {\n // Handle root with config-based keys\n const elementName = root.name || \"root\"; // Default to \"root\" if no name is provided\n const prefix = root[this.config.propNames.prefix] || \"\";\n const qualifiedName = prefix ? `${prefix}:${elementName}` : elementName;\n\n const result: any = {\n [qualifiedName]: {},\n };\n\n // Add attributes to the root element if defined\n const attrsKey = this.config.propNames.attributes;\n if (root[attrsKey] && Array.isArray(root[attrsKey])) {\n result[qualifiedName][attrsKey] = root[attrsKey];\n }\n\n // Merge existing children with the new generated children\n const childrenKey = this.config.propNames.children;\n const children = root[childrenKey] ? root[childrenKey] : [];\n result[qualifiedName][childrenKey] = [\n ...children,\n { [elementName]: wrappedObject },\n ];\n\n // Add namespace and prefix if defined\n const nsKey = this.config.propNames.namespace;\n if (root[nsKey]) {\n result[qualifiedName][nsKey] = root[nsKey];\n }\n\n if (prefix && root[nsKey]) {\n result[qualifiedName][`xmlns:${prefix}`] = root[nsKey];\n }\n\n return result;\n }\n\n // Default behavior if no root is provided\n return wrappedObject;\n }\n\n /**\n * Wraps a standard JSON value in the XML-like JSON structure\n * @param value Value to wrap\n * @returns Wrapped value\n */\n private wrapObject(value: any): any {\n const valKey = this.config.propNames.value;\n const childrenKey = this.config.propNames.children;\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return { [valKey]: value };\n }\n\n if (Array.isArray(value)) {\n // For arrays, wrap each item and return as a children-style array of repeated elements\n return {\n [childrenKey]: value.map((item) => {\n return this.wrapObject(item);\n }),\n };\n }\n\n if (typeof value === \"object\") {\n // It's an object: wrap its properties in children\n const children = Object.entries(value).map(([key, val]) => ({\n [key]: this.wrapObject(val),\n }));\n\n return { [childrenKey]: children };\n }\n\n return undefined; // Fallback for unhandled types\n }\n\n /**\n * Check if an object is empty\n * @param value Value to check\n * @returns true if empty\n */\n isEmpty(value: any): boolean {\n if (value == null) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n }\n\n /**\n * Safely stringify JSON for debugging\n * @param obj Object to stringify\n * @param indent Optional indentation level\n * @returns JSON string representation\n */\n safeStringify(obj: any, indent: number = 2): string {\n try {\n return JSON.stringify(obj, null, indent);\n } catch (error) {\n return \"[Cannot stringify object]\";\n }\n }\n\n /**\n * Deep clone an object\n * @param obj Object to clone\n * @returns Cloned object\n */\n deepClone(obj: any): any {\n try {\n return JSON.parse(JSON.stringify(obj));\n } catch (error) {\n throw new Error(\n `Failed to deep clone object: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Deep merge two objects with proper type handling\n * @param target Target object\n * @param source Source object\n * @returns Merged object (target is modified)\n */\n deepMerge(target: T, source: Partial): T {\n if (!source || typeof source !== \"object\" || source === null) {\n return target;\n }\n\n if (!target || typeof target !== \"object\" || target === null) {\n return source as unknown as T;\n }\n\n Object.keys(source).forEach((key) => {\n const sourceValue = source[key as keyof Partial];\n const targetValue = target[key as keyof T];\n\n // If both source and target values are objects, recursively merge them\n if (\n sourceValue !== null &&\n targetValue !== null &&\n typeof sourceValue === \"object\" &&\n typeof targetValue === \"object\" &&\n !Array.isArray(sourceValue) &&\n !Array.isArray(targetValue)\n ) {\n // Recursively merge the nested objects\n (target as any)[key] = this.deepMerge(targetValue, sourceValue as any);\n } else {\n // Otherwise just replace the value\n (target as any)[key] = sourceValue;\n }\n });\n\n return target;\n }\n\n /**\n * Generates a JSON schema that matches the current configuration\n * @returns JSON schema object\n */\n generateJsonSchema(): Record {\n try {\n const propNames = this.config.propNames;\n const compact = this.config.outputOptions.compact || false;\n const preserveNamespaces = this.config.preserveNamespaces;\n const preserveComments = this.config.preserveComments;\n const preserveCDATA = this.config.preserveCDATA;\n const preserveProcessingInstr = this.config.preserveProcessingInstr;\n const preserveTextNodes = this.config.preserveTextNodes;\n const preserveWhitespace = this.config.preserveWhitespace;\n const preserveAttributes = this.config.preserveAttributes;\n\n // Determine which properties are required based on the configuration\n const requiredProps: string[] = [];\n\n if (!compact) {\n // Only add collections as required if they're preserved in the config\n if (preserveAttributes) requiredProps.push(propNames.attributes);\n\n if (preserveCDATA) requiredProps.push(propNames.cdata);\n if (preserveComments) requiredProps.push(propNames.comments);\n if (preserveProcessingInstr) requiredProps.push(propNames.instruction);\n requiredProps.push(propNames.children);\n\n if (preserveTextNodes) {\n requiredProps.push(propNames.value);\n\n if (preserveNamespaces) {\n requiredProps.push(propNames.namespace);\n // Note: prefix is not required as it may not be present for all elements\n }\n }\n }\n\n // Create schema for element properties\n const elementProperties: Record = {};\n\n // Add namespace property if preserving namespaces\n if (preserveNamespaces) {\n elementProperties[propNames.namespace] = {\n description: \"Namespace URI of the element\",\n type: \"string\",\n };\n\n // Add prefix property if preserving namespaces\n elementProperties[propNames.prefix] = {\n description: \"Namespace prefix of the element\",\n type: \"string\",\n };\n }\n\n // Add value property if preserving text nodes\n if (preserveTextNodes) {\n elementProperties[propNames.value] = {\n description: \"Text content of the element\",\n type: \"string\",\n };\n }\n\n // Add attributes property\n if (preserveAttributes) {\n elementProperties[propNames.attributes] = {\n description: \"Element attributes\",\n type: \"array\",\n items: {\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n type: \"object\",\n properties: {\n [propNames.value]: {\n description: \"Attribute value\",\n type: \"string\",\n },\n },\n required: [propNames.value],\n },\n },\n additionalProperties: false,\n },\n };\n\n // If preserving namespaces, add namespace properties to attribute schema\n if (preserveNamespaces) {\n const attrProps =\n elementProperties[propNames.attributes].items.patternProperties[\n \"^.*$\"\n ].properties;\n\n attrProps[propNames.namespace] = {\n description: \"Namespace URI of the attribute\",\n type: \"string\",\n };\n\n attrProps[propNames.prefix] = {\n description: \"Namespace prefix of the attribute\",\n type: \"string\",\n };\n }\n }\n\n // Add CDATA property if preserving CDATA\n if (preserveCDATA) {\n elementProperties[propNames.cdata] = {\n description: \"CDATA section content\",\n type: \"string\",\n };\n }\n\n // Add comments property if preserving comments\n if (preserveComments) {\n elementProperties[propNames.comments] = {\n description: \"Comment content\",\n type: \"string\",\n };\n }\n\n // Add processing instructions property if preserving them\n if (preserveProcessingInstr) {\n elementProperties[propNames.instruction] = {\n description: \"Processing instruction\",\n type: \"object\",\n properties: {\n [propNames.target]: {\n description: \"Processing instruction target\",\n type: \"string\",\n },\n [propNames.value]: {\n description: \"Processing instruction content\",\n type: \"string\",\n },\n },\n required: [propNames.target],\n };\n }\n\n // Add children property with recursive schema\n elementProperties[propNames.children] = {\n description: \"Child elements\",\n type: \"array\",\n items: {\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n $ref: \"#/definitions/element\",\n },\n },\n additionalProperties: false,\n },\n };\n\n // Create element definition (will be referenced recursively)\n const elementDefinition = {\n type: \"object\",\n properties: elementProperties,\n required: requiredProps,\n additionalProperties: false,\n };\n\n // Build the complete schema\n const schema = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n title: \"XJX JSON Schema\",\n description:\n \"Schema for JSON representation of XML documents using the XJX library\",\n type: \"object\",\n patternProperties: {\n \"^.*$\": {\n $ref: \"#/definitions/element\",\n },\n },\n additionalProperties: false,\n definitions: {\n element: elementDefinition,\n },\n };\n\n return schema;\n } catch (error) {\n throw new Error(\n `Schema generation failed: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Generate an example JSON object based on the schema\n * @param {string} rootName - Name of the root element\n * @returns {Record} - Example JSON object\n */\n generateExample(rootName: string = \"root\"): Record {\n const propNames = this.config.propNames;\n const preserveNamespaces = this.config.preserveNamespaces;\n const preserveComments = this.config.preserveComments;\n const preserveCDATA = this.config.preserveCDATA;\n const preserveProcessingInstr = this.config.preserveProcessingInstr;\n const preserveAttributes = this.config.preserveAttributes;\n\n // Simple example with common features\n const example: Record = {\n [rootName]: {\n [propNames.value]: \"Root content\",\n [propNames.children]: [\n {\n child: {\n [propNames.value]: \"Child content\",\n },\n },\n ],\n },\n };\n\n // Add namespace properties if enabled\n if (preserveNamespaces) {\n example[rootName][propNames.namespace] = \"http://example.org/ns\";\n example[rootName][propNames.prefix] = \"ex\";\n example[rootName][propNames.children][0].child[propNames.namespace] =\n \"http://example.org/ns\";\n example[rootName][propNames.children][0].child[propNames.prefix] = \"ex\";\n }\n\n // Add attributes if enabled\n if (preserveAttributes) {\n example[rootName][propNames.attributes] = [\n { id: { [propNames.value]: \"root-1\" } },\n { lang: { [propNames.value]: \"en\" } },\n ];\n\n if (preserveNamespaces) {\n example[rootName][propNames.attributes][1].lang[propNames.prefix] =\n \"xml\";\n }\n\n example[rootName][propNames.children][0].child[propNames.attributes] = [\n { id: { [propNames.value]: \"child-1\" } },\n ];\n }\n\n // Add CDATA if enabled\n if (preserveCDATA) {\n example[rootName][propNames.children][0].child[propNames.children] = [\n { [propNames.cdata]: \"Raw content\" },\n ];\n }\n\n // Add comments if enabled\n if (preserveComments) {\n if (!example[rootName][propNames.children][0].child[propNames.children]) {\n example[rootName][propNames.children][0].child[propNames.children] = [];\n }\n\n example[rootName][propNames.children][0].child[propNames.children].push({\n [propNames.comments]: \"Comment about the child\",\n });\n }\n\n // Add processing instruction if enabled\n if (preserveProcessingInstr) {\n if (!example[rootName][propNames.children]) {\n example[rootName][propNames.children] = [];\n }\n\n example[rootName][propNames.children].unshift({\n [propNames.instruction]: {\n [propNames.target]: \"xml-stylesheet\",\n [propNames.value]: 'type=\"text/css\" href=\"style.css\"',\n },\n });\n }\n\n return example;\n }\n}\n","/**\n * Utilities for applying value transformations\n */\nimport { Configuration } from '../types/config-types';\nimport { TransformContext, TransformDirection } from './ValueTransformer';\nimport { DOMAdapter } from '../adapters/dom-adapter';\n\n/**\n * Utility for applying value transformations\n */\nexport class TransformUtil {\n private config: Configuration;\n\n /**\n * Create a new TransformUtil\n * @param config Configuration\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Apply transforms to a value\n * @param value Value to transform\n * @param context Transformation context\n * @returns Transformed value\n */\n applyTransforms(value: any, context: TransformContext): any {\n // Skip transformation if no transformers are configured\n if (!this.config.valueTransforms || this.config.valueTransforms.length === 0) {\n return value;\n }\n\n // Apply each transformer in sequence\n let transformedValue = value;\n for (const transformer of this.config.valueTransforms) {\n transformedValue = transformer.process(transformedValue, context);\n }\n\n return transformedValue;\n }\n\n /**\n * Create a transform context\n * @param direction Direction of transformation\n * @param nodeName Name of the current node\n * @param nodeType DOM node type\n * @param options Additional context options\n * @returns Transform context\n */\n createContext(\n direction: TransformDirection,\n nodeName: string,\n nodeType: number,\n options: {\n path?: string;\n namespace?: string;\n prefix?: string;\n isAttribute?: boolean;\n attributeName?: string;\n parent?: TransformContext;\n } = {}\n ): TransformContext {\n return {\n direction,\n nodeName,\n nodeType,\n path: options.path || nodeName,\n namespace: options.namespace,\n prefix: options.prefix,\n isAttribute: options.isAttribute || false,\n attributeName: options.attributeName,\n parent: options.parent,\n config: this.config,\n };\n }\n\n /**\n * Get a user-friendly node type name for debugging\n * @param nodeType DOM node type\n * @returns String representation of node type\n */\n getNodeTypeName(nodeType: number): string {\n return DOMAdapter.getNodeTypeName(nodeType);\n }\n}","/**\n * XmlToJsonConverter class for converting XML to JSON with consistent namespace handling\n */\nimport { Configuration } from \"../types/config-types\";\nimport { XJXError } from \"../types/error-types\";\nimport { DOMAdapter } from \"../adapters/dom-adapter\";\nimport { JsonUtil } from \"../utils/json-utils\";\nimport { TransformUtil } from \"../transformers/TransformUtil\";\nimport { TransformContext } from \"../transformers/ValueTransformer\";\n\n/**\n * XmlToJsonConverter Parser for converting XML to JSON\n */\nexport class XmlToJsonConverter {\n private config: Configuration;\n private jsonUtil: JsonUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for XmlToJsonConverter\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.jsonUtil = new JsonUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public convert(xmlString: string): Record {\n try {\n const xmlDoc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n // Check for parsing errors\n const errors = xmlDoc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n throw new XJXError(`XML parsing error: ${errors[0].textContent}`);\n }\n\n return this.nodeToJson(xmlDoc.documentElement);\n } catch (error) {\n throw new XJXError(\n `Failed to convert XML to JSON: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert a DOM node to JSON representation\n * @param node DOM node to convert\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the XML tree\n * @returns JSON representation of the node\n */\n private nodeToJson(node: Node, parentContext?: TransformContext, path: string = \"\"): Record {\n const result: Record = {};\n\n // Handle element nodes\n if (node.nodeType === DOMAdapter.NodeType.ELEMENT_NODE) {\n const element = node as Element;\n // Use localName instead of nodeName to strip namespace prefix\n const nodeName =\n element.localName ||\n element.nodeName.split(\":\").pop() ||\n element.nodeName;\n\n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n const nodeObj: Record = {};\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: currentPath,\n namespace: element.namespaceURI || undefined,\n prefix: element.prefix || undefined,\n parent: parentContext\n }\n );\n\n // Process namespaces if enabled\n if (this.config.preserveNamespaces) {\n const ns = element.namespaceURI;\n if (ns) {\n nodeObj[this.config.propNames.namespace] = ns;\n }\n\n const prefix = element.prefix;\n if (prefix) {\n nodeObj[this.config.propNames.prefix] = prefix;\n }\n }\n\n // Process attributes if enabled\n if (this.config.preserveAttributes && element.attributes.length > 0) {\n const attrs: Array> = [];\n\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n // Strip namespace prefix from attribute name\n const attrLocalName =\n attr.localName || attr.name.split(\":\").pop() || attr.name;\n\n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'xml-to-json',\n nodeName,\n node.nodeType,\n {\n path: `${currentPath}.${attrLocalName}`,\n namespace: attr.namespaceURI || undefined,\n prefix: attr.prefix || undefined,\n isAttribute: true,\n attributeName: attrLocalName,\n parent: context\n }\n );\n\n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attr.value,\n attrContext\n );\n\n // Create attribute object with consistent structure\n const attrObj: Record = {\n [attrLocalName]: {\n [this.config.propNames.value]: transformedValue,\n },\n };\n\n // Add namespace info for attribute if present and enabled\n if (this.config.preserveNamespaces) {\n // Handle attribute namespace\n if (attr.namespaceURI) {\n attrObj[attrLocalName][this.config.propNames.namespace] =\n attr.namespaceURI;\n }\n\n // Handle attribute prefix\n if (attr.prefix) {\n attrObj[attrLocalName][this.config.propNames.prefix] =\n attr.prefix;\n }\n }\n\n attrs.push(attrObj);\n }\n\n if (attrs.length > 0) {\n nodeObj[this.config.propNames.attributes] = attrs;\n }\n }\n\n // Process child nodes\n if (element.childNodes.length > 0) {\n const children: Array> = [];\n const childrenKey = this.config.propNames.children;\n const valueKey = this.config.propNames.value;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n\n // Text nodes - only process if preserveTextNodes is true\n if (child.nodeType === DOMAdapter.NodeType.TEXT_NODE) {\n if (this.config.preserveTextNodes) {\n let text = child.nodeValue || \"\";\n\n // Skip whitespace-only text nodes if whitespace preservation is disabled\n if (!this.config.preserveWhitespace) {\n if (text.trim() === \"\") {\n continue;\n }\n // Trim the text when preserveWhitespace is false\n text = text.trim();\n }\n\n // Create text node context\n const textContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#text',\n child.nodeType,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n\n // Apply transformations to text value\n const transformedText = this.transformUtil.applyTransforms(\n text,\n textContext\n );\n\n children.push({ [valueKey]: transformedText });\n }\n }\n // CDATA sections\n else if (\n child.nodeType === DOMAdapter.NodeType.CDATA_SECTION_NODE &&\n this.config.preserveCDATA\n ) {\n // Create CDATA context\n const cdataContext = this.transformUtil.createContext(\n 'xml-to-json',\n '#cdata',\n child.nodeType,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n\n // Apply transformations to CDATA value\n const transformedCData = this.transformUtil.applyTransforms(\n child.nodeValue || \"\",\n cdataContext\n );\n\n children.push({\n [cdataKey]: transformedCData,\n });\n }\n // Comments\n else if (\n child.nodeType === DOMAdapter.NodeType.COMMENT_NODE &&\n this.config.preserveComments\n ) {\n children.push({\n [commentsKey]: child.nodeValue || \"\",\n });\n }\n // Processing instructions\n else if (\n child.nodeType ===\n DOMAdapter.NodeType.PROCESSING_INSTRUCTION_NODE &&\n this.config.preserveProcessingInstr\n ) {\n children.push({\n [instructionKey]: {\n [targetKey]: child.nodeName,\n [valueKey]: child.nodeValue || \"\",\n },\n });\n }\n // Element nodes (recursive)\n else if (child.nodeType === DOMAdapter.NodeType.ELEMENT_NODE) {\n children.push(this.nodeToJson(child, context, currentPath));\n }\n }\n\n if (children.length > 0) {\n nodeObj[childrenKey] = children;\n }\n }\n\n // Apply compact option - remove empty properties if enabled\n if (this.config.outputOptions.compact) {\n Object.keys(nodeObj).forEach((key) => {\n const cleaned = this.cleanNode(nodeObj[key]);\n if (cleaned === undefined) {\n delete nodeObj[key];\n } else {\n nodeObj[key] = cleaned;\n }\n });\n }\n\n result[nodeName] = nodeObj;\n }\n\n return result;\n }\n\n private cleanNode(node: any): any {\n if (Array.isArray(node)) {\n // Clean each item in the array and filter out empty ones\n const cleanedArray = node\n .map((item) => this.cleanNode(item))\n .filter((item) => {\n return !(\n item === null ||\n item === undefined ||\n (typeof item === \"object\" && Object.keys(item).length === 0)\n );\n });\n return cleanedArray.length > 0 ? cleanedArray : undefined;\n } else if (typeof node === \"object\" && node !== null) {\n // Clean properties recursively\n Object.keys(node).forEach((key) => {\n const cleanedChild = this.cleanNode(node[key]);\n if (\n cleanedChild === null ||\n cleanedChild === undefined ||\n (Array.isArray(cleanedChild) && cleanedChild.length === 0) ||\n (typeof cleanedChild === \"object\" &&\n Object.keys(cleanedChild).length === 0)\n ) {\n delete node[key];\n } else {\n node[key] = cleanedChild;\n }\n });\n\n // Handle the special case for nodes with only empty children/attributes\n const childrenKey = this.config.propNames.children;\n const attrsKey = this.config.propNames.attributes;\n const keys = Object.keys(node);\n if (\n keys.every((key) => key === childrenKey || key === attrsKey) &&\n (node[childrenKey] === undefined ||\n this.jsonUtil.isEmpty(node[childrenKey])) &&\n (node[attrsKey] === undefined || this.jsonUtil.isEmpty(node[attrsKey]))\n ) {\n return undefined;\n }\n\n return Object.keys(node).length > 0 ? node : undefined;\n }\n\n return node;\n }\n}","/**\n * XMLUtil - Utility functions for XML processing\n */\nimport { XJXError } from \"../types/error-types\";\nimport { DOMAdapter } from \"../adapters/dom-adapter\";\nimport { Configuration } from \"../types/config-types\";\n\nexport class XmlUtil {\n private config: Configuration;\n\n /**\n * Constructor for XMLUtil\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n prettyPrintXml(xmlString: string): string {\n const indent = this.config.outputOptions.indent;\n const INDENT = \" \".repeat(indent);\n\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n\n const serializer = (node: Node, level = 0): string => {\n const pad = INDENT.repeat(level);\n\n switch (node.nodeType) {\n case DOMAdapter.NodeType.ELEMENT_NODE: {\n const el = node as Element;\n const tagName = el.tagName;\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const openTag = attrs ? `<${tagName} ${attrs}>` : `<${tagName}>`;\n\n const children = Array.from(el.childNodes);\n\n if (children.length === 0) {\n return `${pad}${openTag.replace(/>$/, \" />\")}\\n`;\n }\n\n // Single text node: print inline\n if (\n children.length === 0 ||\n (children.length === 1 &&\n children[0].nodeType === DOMAdapter.NodeType.TEXT_NODE &&\n children[0].textContent?.trim() === \"\")\n ) {\n // Empty or whitespace-only\n return `${pad}<${tagName}${attrs ? \" \" + attrs : \"\"}>\\n`;\n }\n\n const inner = children\n .map((child) => serializer(child, level + 1))\n .join(\"\");\n return `${pad}${openTag}\\n${inner}${pad}\\n`;\n }\n\n case DOMAdapter.NodeType.TEXT_NODE: {\n const text = node.textContent?.trim();\n return text ? `${pad}${text}\\n` : \"\";\n }\n\n case DOMAdapter.NodeType.CDATA_SECTION_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.NodeType.COMMENT_NODE:\n return `${pad}\\n`;\n\n case DOMAdapter.NodeType.PROCESSING_INSTRUCTION_NODE:\n const pi = node as ProcessingInstruction;\n return `${pad}\\n`;\n\n case DOMAdapter.NodeType.DOCUMENT_NODE:\n return Array.from(node.childNodes)\n .map((child) => serializer(child, level))\n .join(\"\");\n\n default:\n return \"\";\n }\n };\n\n return serializer(doc).trim();\n } catch (error) {\n throw new XJXError(\n `Failed to pretty print XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Check if XML string is well-formed\n * @param xmlString XML string to validate\n * @returns Object with validation result and any error messages\n */\n validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n try {\n const doc = DOMAdapter.parseFromString(xmlString, \"text/xml\");\n const errors = doc.getElementsByTagName(\"parsererror\");\n if (errors.length > 0) {\n return {\n isValid: false,\n message: errors[0].textContent || \"Unknown parsing error\",\n };\n }\n return { isValid: true };\n } catch (error) {\n return {\n isValid: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Add XML declaration to a string if missing\n * @param xmlString XML string\n * @returns XML string with declaration\n */\n ensureXMLDeclaration(xmlString: string): string {\n if (!xmlString.trim().startsWith(\"\\n' + xmlString;\n }\n return xmlString;\n }\n\n /**\n * Escapes special characters in text for safe XML usage.\n * @param text Text to escape.\n * @returns Escaped XML string.\n */\n escapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&\";\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case '\"':\n return \""\";\n case \"'\":\n return \"'\";\n default:\n return char;\n }\n });\n }\n\n /**\n * Unescapes XML entities back to their character equivalents.\n * @param text Text with XML entities.\n * @returns Unescaped text.\n */\n unescapeXML(text: string): string {\n if (typeof text !== \"string\" || text.length === 0) {\n return \"\";\n }\n\n return text.replace(/&(amp|lt|gt|quot|apos);/g, (match, entity) => {\n switch (entity) {\n case \"amp\":\n return \"&\";\n case \"lt\":\n return \"<\";\n case \"gt\":\n return \">\";\n case \"quot\":\n return '\"';\n case \"apos\":\n return \"'\";\n default:\n return match;\n }\n });\n }\n\n /**\n * Extract the namespace prefix from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Prefix or null if no prefix\n */\n extractPrefix(qualifiedName: string): string | null {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0 ? qualifiedName.substring(0, colonIndex) : null;\n }\n\n /**\n * Extract the local name from a qualified name\n * @param qualifiedName Qualified name (e.g., \"ns:element\")\n * @returns Local name\n */\n extractLocalName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(\":\");\n return colonIndex > 0\n ? qualifiedName.substring(colonIndex + 1)\n : qualifiedName;\n }\n\n /**\n * Create a qualified name from prefix and local name\n * @param prefix Namespace prefix (can be null)\n * @param localName Local name\n * @returns Qualified name\n */\n createQualifiedName(prefix: string | null, localName: string): string {\n return prefix ? `${prefix}:${localName}` : localName;\n }\n}","/**\n * JsonToXmlConverter class for converting JSON to XML with consistent namespace handling\n */\nimport { Configuration } from \"../types/config-types\";\nimport { XJXError } from \"../types/error-types\";\nimport { DOMAdapter } from \"../adapters/dom-adapter\";\nimport { XmlUtil } from \"../utils/xml-utils\";\nimport { TransformUtil } from \"../transformers/TransformUtil\";\nimport { TransformContext } from \"../transformers/ValueTransformer\";\n\n/**\n * JsonToXmlConverter for converting JSON to XML\n */\nexport class JsonToXmlConverter {\n private config: Configuration;\n private xmlUtil: XmlUtil;\n private transformUtil: TransformUtil;\n\n /**\n * Constructor for JsonToXmlConverter\n * @param config Configuration options\n */\n constructor(config: Configuration) {\n this.config = config;\n this.xmlUtil = new XmlUtil(this.config);\n this.transformUtil = new TransformUtil(this.config);\n }\n\n /**\n * Convert JSON object to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public convert(jsonObj: Record): string {\n try {\n const doc = DOMAdapter.createDocument();\n const rootElement = this.jsonToNode(jsonObj, doc);\n\n if (rootElement) {\n // Handle the temporary root element if it exists\n if (doc.documentElement && doc.documentElement.nodeName === \"temp\") {\n doc.replaceChild(rootElement, doc.documentElement);\n } else {\n doc.appendChild(rootElement);\n }\n }\n\n // Add XML declaration if specified\n let xmlString = DOMAdapter.serializeToString(doc);\n\n // remove xhtml decl inserted by dom\n xmlString = xmlString.replace(' xmlns=\"http://www.w3.org/1999/xhtml\"', '');\n\n if (this.config.outputOptions.xml.declaration) {\n xmlString = this.xmlUtil.ensureXMLDeclaration(xmlString);\n }\n\n // Apply pretty printing if enabled\n if (this.config.outputOptions.prettyPrint) {\n xmlString = this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n return xmlString;\n } catch (error) {\n throw new XJXError(\n `Failed to convert JSON to XML: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Convert JSON object to DOM node\n * @param jsonObj JSON object to convert\n * @param doc Document for creating elements\n * @param parentContext Optional parent context for transformation chain\n * @param path Current path in the JSON object\n * @returns DOM Element\n */\n private jsonToNode(\n jsonObj: Record,\n doc: Document,\n parentContext?: TransformContext,\n path: string = \"\"\n ): Element | null {\n if (!jsonObj || typeof jsonObj !== \"object\") {\n return null;\n }\n\n // Get the node name (first key in the object)\n const nodeName = Object.keys(jsonObj)[0];\n if (!nodeName) {\n return null;\n }\n\n const nodeData = jsonObj[nodeName];\n \n // Update the current path\n const currentPath = path ? `${path}.${nodeName}` : nodeName;\n\n // Create element with namespace if available\n let element: Element;\n const namespaceKey = this.config.propNames.namespace;\n const prefixKey = this.config.propNames.prefix;\n const ns = nodeData[namespaceKey];\n const prefix = nodeData[prefixKey];\n\n // Create context for this node\n const context = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.NodeType.ELEMENT_NODE,\n {\n path: currentPath,\n namespace: ns,\n prefix: prefix,\n parent: parentContext\n }\n );\n\n if (ns && this.config.preserveNamespaces) {\n if (prefix) {\n // Create element with namespace and prefix\n element = DOMAdapter.createElementNS(ns, `${prefix}:${nodeName}`);\n } else {\n // Create element with namespace but no prefix\n element = DOMAdapter.createElementNS(ns, nodeName);\n }\n } else {\n // Create element without namespace\n element = DOMAdapter.createElement(nodeName);\n }\n\n // Process attributes if enabled\n const attributesKey = this.config.propNames.attributes;\n const valueKey = this.config.propNames.value;\n if (\n this.config.preserveAttributes &&\n nodeData[attributesKey] &&\n Array.isArray(nodeData[attributesKey])\n ) {\n nodeData[attributesKey].forEach(\n (attrObj: Record) => {\n const attrName = Object.keys(attrObj)[0];\n if (!attrName) return;\n\n const attrData = attrObj[attrName];\n \n // Create attribute context\n const attrContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.NodeType.ELEMENT_NODE,\n {\n path: `${currentPath}.${attrName}`,\n namespace: attrData[namespaceKey],\n prefix: attrData[prefixKey],\n isAttribute: true,\n attributeName: attrName,\n parent: context\n }\n );\n \n // Apply transformations to attribute value\n const transformedValue = this.transformUtil.applyTransforms(\n attrData[valueKey] || \"\",\n attrContext\n );\n \n const attrNs = attrData[namespaceKey];\n const attrPrefix = attrData[prefixKey];\n\n // Form qualified name for attribute if it has a prefix\n let qualifiedName = attrName;\n if (attrPrefix && this.config.preserveNamespaces) {\n qualifiedName = `${attrPrefix}:${attrName}`;\n }\n\n DOMAdapter.setNamespacedAttribute(\n element, \n (attrNs && this.config.preserveNamespaces) ? attrNs : null, \n qualifiedName, \n transformedValue\n );\n }\n );\n }\n\n // Process simple text value\n if (nodeData[valueKey] !== undefined) {\n // Apply transformations to text value\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n nodeName,\n DOMAdapter.NodeType.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n namespace: ns,\n prefix: prefix,\n parent: context\n }\n );\n \n const transformedValue = this.transformUtil.applyTransforms(\n nodeData[valueKey],\n textContext\n );\n \n element.textContent = transformedValue;\n }\n\n // Process children\n const childrenKey = this.config.propNames.children;\n const cdataKey = this.config.propNames.cdata;\n const commentsKey = this.config.propNames.comments;\n const instructionKey = this.config.propNames.instruction;\n const targetKey = this.config.propNames.target;\n\n if (\n nodeData[childrenKey] &&\n Array.isArray(nodeData[childrenKey])\n ) {\n nodeData[childrenKey].forEach(\n (child: Record) => {\n // Text nodes\n if (\n child[valueKey] !== undefined &&\n this.config.preserveTextNodes\n ) {\n // Apply transformations to text node\n const textContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#text',\n DOMAdapter.NodeType.TEXT_NODE,\n {\n path: `${currentPath}.#text`,\n parent: context\n }\n );\n \n const transformedText = this.transformUtil.applyTransforms(\n child[valueKey],\n textContext\n );\n \n element.appendChild(\n DOMAdapter.createTextNode(this.xmlUtil.escapeXML(transformedText))\n );\n }\n // CDATA sections\n else if (\n child[cdataKey] !== undefined &&\n this.config.preserveCDATA\n ) {\n // Apply transformations to CDATA\n const cdataContext = this.transformUtil.createContext(\n 'json-to-xml',\n '#cdata',\n DOMAdapter.NodeType.CDATA_SECTION_NODE,\n {\n path: `${currentPath}.#cdata`,\n parent: context\n }\n );\n \n const transformedCData = this.transformUtil.applyTransforms(\n child[cdataKey],\n cdataContext\n );\n \n element.appendChild(\n DOMAdapter.createCDATASection(\n transformedCData\n )\n );\n }\n // Comments\n else if (\n child[commentsKey] !== undefined &&\n this.config.preserveComments\n ) {\n element.appendChild(\n DOMAdapter.createComment(\n child[commentsKey]\n )\n );\n }\n // Processing instructions\n else if (\n child[instructionKey] !== undefined &&\n this.config.preserveProcessingInstr\n ) {\n const piData = child[instructionKey];\n const target = piData[targetKey];\n const data = piData[valueKey] || \"\";\n\n if (target) {\n element.appendChild(\n DOMAdapter.createProcessingInstruction(target, data)\n );\n }\n }\n // Element nodes (recursive)\n else {\n const childElement = this.jsonToNode(child, doc, context, currentPath);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n }\n );\n }\n\n return element;\n }\n}","/**\n * Default configuration for the XJX library\n */\nimport { Configuration } from '../types/config-types';\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: Configuration = {\n preserveNamespaces: true,\n preserveComments: true,\n preserveProcessingInstr: true,\n preserveCDATA: true,\n preserveTextNodes: true,\n preserveWhitespace: false,\n preserveAttributes: true,\n\n outputOptions: {\n prettyPrint: true,\n indent: 2,\n compact: true,\n json: {},\n xml: {\n declaration: true,\n },\n },\n\n propNames: {\n namespace: \"$ns\",\n prefix: \"$pre\",\n attributes: \"$attr\",\n value: \"$val\",\n cdata: \"$cdata\",\n comments: \"$cmnt\",\n instruction: \"$pi\", \n target: \"$trgt\", \n children: \"$children\",\n },\n};","/**\n * XJX - Facade class for XML-JSON conversion operations\n */\nimport { XmlToJsonConverter } from \"./core/converters/xml-to-json-converter\";\nimport { JsonToXmlConverter } from \"./core/converters/json-to-xml-converter\";\nimport { Configuration } from \"./core/types/config-types\";\nimport { DEFAULT_CONFIG } from \"./core/config/config\";\nimport { DOMAdapter } from \"./core/adapters/dom-adapter\";\nimport { XmlUtil } from \"./core/utils/xml-utils\";\nimport { JsonUtil } from \"./core/utils/json-utils\";\nimport { ValueTransformer } from \"./core/transformers\";\n\nexport class XJX {\n private config: Configuration;\n private xmlToJsonConverter: XmlToJsonConverter;\n private jsonToXmlConverter: JsonToXmlConverter;\n private jsonUtil: JsonUtil;\n private xmlUtil: XmlUtil;\n\n /**\n * Constructor for XJX utility\n * @param config Configuration options\n */\n constructor(config: Partial = {}) {\n // First create a jsonUtil instance with default config to use its methods\n this.jsonUtil = new JsonUtil(DEFAULT_CONFIG);\n\n // Create a deep clone of the default config\n const defaultClone = this.jsonUtil.deepClone(DEFAULT_CONFIG);\n\n // Deep merge with the provided config\n this.config = this.jsonUtil.deepMerge(defaultClone, config);\n\n // Re-initialize jsonUtil with the merged config\n this.jsonUtil = new JsonUtil(this.config);\n\n // Initialize other components\n this.xmlUtil = new XmlUtil(this.config);\n this.xmlToJsonConverter = new XmlToJsonConverter(this.config);\n this.jsonToXmlConverter = new JsonToXmlConverter(this.config);\n }\n\n /**\n * Convert XML string to JSON\n * @param xmlString XML content as string\n * @returns JSON object representing the XML content\n */\n public xmlToJson(xmlString: string): Record {\n return this.xmlToJsonConverter.convert(xmlString);\n }\n\n /**\n * Convert JSON object back to XML string\n * @param jsonObj JSON object to convert\n * @returns XML string\n */\n public jsonToXml(jsonObj: Record): string {\n return this.jsonToXmlConverter.convert(jsonObj);\n }\n\n /**\n * Pretty print an XML string\n * @param xmlString XML string to format\n * @returns Formatted XML string\n */\n public prettyPrintXml(xmlString: string): string {\n return this.xmlUtil.prettyPrintXml(xmlString);\n }\n\n /**\n * Safely retrieves a value from a JSON object using a dot-separated path.\n * @param obj The input JSON object\n * @param path The dot-separated path string (e.g., \"root.item.description.$val\")\n * @param fallback Value to return if the path does not resolve\n * @returns The value at the specified path or the fallback value\n */\n public getPath(\n obj: Record,\n path: string,\n fallback: any = undefined\n ): any {\n return this.jsonUtil.getPath(obj, path, fallback);\n }\n\n /**\n * Validate XML string\n * @param xmlString XML string to validate\n * @returns Validation result\n */\n public validateXML(xmlString: string): {\n isValid: boolean;\n message?: string;\n } {\n return this.xmlUtil.validateXML(xmlString);\n }\n\n /**\n * Generate a JSON schema based on the current configuration\n * @returns JSON schema object for validating XML-JSON documents\n */\n public generateJsonSchema(): Record {\n return this.jsonUtil.generateJsonSchema();\n }\n\n /**\n * Convert a standard JSON object to the XML-like JSON structure\n * @param obj Standard JSON object\n * @param root Optional root element configuration (string or object with properties)\n * @returns XML-like JSON object ready for conversion to XML\n */\n public objectToXJX(obj: any, root?: string | Record): Record {\n return this.jsonUtil.objectToXJX(obj, root);\n }\n\n /**\n * Generate an example JSON object that matches the current configuration\n * @param rootName Name of the root element\n * @returns Example JSON object\n */\n public generateJsonExample(rootName: string = \"root\"): Record {\n return this.jsonUtil.generateExample(rootName);\n }\n\n /**\n * Add a value transformer to the configuration\n * @param transformer Value transformer to add\n * @returns This XJX instance for chaining\n */\n public addTransformer(transformer: ValueTransformer): XJX {\n if (!this.config.valueTransforms) {\n this.config.valueTransforms = [];\n }\n this.config.valueTransforms.push(transformer);\n return this;\n }\n\n /**\n * Removes all value transformers from the configuration\n * @returns This XJX instance for chaining\n */\n public clearTransformers(): XJX {\n this.config.valueTransforms = [];\n return this;\n }\n\n /**\n * Clean up any resources\n */\n public cleanup(): void {\n DOMAdapter.cleanup();\n }\n}","/**\n * Value transformation types and base class for the XJX library\n */\nimport { Configuration } from '../types/config-types';\n\n/**\n * Direction of the transformation\n */\nexport type TransformDirection = 'xml-to-json' | 'json-to-xml';\n\n/**\n * Context provided to value transformers\n */\nexport interface TransformContext {\n // Core transformation info\n direction: TransformDirection; // Direction of the current transformation\n \n // Node information\n nodeName: string; // Name of the current node\n nodeType: number; // DOM node type (element, text, etc.)\n namespace?: string; // Namespace URI if available\n prefix?: string; // Namespace prefix if available\n \n // Structure information\n path: string; // Dot-notation path to current node\n isAttribute: boolean; // Whether the current value is from an attribute\n attributeName?: string; // Name of attribute if isAttribute is true\n \n // Parent context (creates a chain)\n parent?: TransformContext; // Reference to parent context for traversal\n \n // Configuration reference\n config: Configuration; // Reference to the current configuration\n}\n\n/**\n * Abstract base class for value transformers\n */\nexport abstract class ValueTransformer {\n /**\n * Process a value, transforming it if applicable\n * @param value Value to potentially transform\n * @param context Context including direction and other information\n * @returns Transformed value or original if not applicable\n */\n process(value: any, context: TransformContext): any {\n if (context.direction === 'xml-to-json') {\n return this.xmlToJson(value, context);\n } else {\n return this.jsonToXml(value, context);\n }\n }\n\n /**\n * Transform a value from XML to JSON representation\n * @param value Value from XML\n * @param context Transformation context\n * @returns Transformed value for JSON\n */\n protected xmlToJson(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n\n /**\n * Transform a value from JSON to XML representation\n * @param value Value from JSON\n * @param context Transformation context\n * @returns Transformed value for XML\n */\n protected jsonToXml(value: any, context: TransformContext): any {\n // Default implementation returns original value\n return value;\n }\n}","// Import locally so you can use it below\nimport { XJX } from './XJX';\n\n// Core components\nexport { XJX };\nexport { Configuration } from './core/types/config-types';\nexport { DEFAULT_CONFIG } from './core/config/config';\n\n// Error handling\nexport { XJXError } from './core/types/error-types';\n\n// Allow custom transformers\nexport { ValueTransformer } from './core/transformers/ValueTransformer';\n\n// Default export\nexport default XJX;"],"names":[],"mappings":"AAAA;;AAEG;AAEH;;AAEG;AACG,MAAO,QAAS,SAAQ,KAAK,CAAA;AACjC,IAAA,WAAA,CAAY,OAAe,EAAA;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;AACf,QAAA,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;KAC9B;AACF;;ACZD;;AAEG;AACH,IAAY,QAQT,CAAA;AARH,CAAA,UAAY,QAAQ,EAAA;AAChB,IAAA,QAAA,CAAA,QAAA,CAAA,cAAA,CAAA,GAAA,CAAA,CAAA,GAAA,cAAgB,CAAA;AAChB,IAAA,QAAA,CAAA,QAAA,CAAA,gBAAA,CAAA,GAAA,CAAA,CAAA,GAAA,gBAAkB,CAAA;AAClB,IAAA,QAAA,CAAA,QAAA,CAAA,WAAA,CAAA,GAAA,CAAA,CAAA,GAAA,WAAa,CAAA;AACb,IAAA,QAAA,CAAA,QAAA,CAAA,oBAAA,CAAA,GAAA,CAAA,CAAA,GAAA,oBAAsB,CAAA;AACtB,IAAA,QAAA,CAAA,QAAA,CAAA,6BAAA,CAAA,GAAA,CAAA,CAAA,GAAA,6BAA+B,CAAA;AAC/B,IAAA,QAAA,CAAA,QAAA,CAAA,cAAA,CAAA,GAAA,CAAA,CAAA,GAAA,cAAgB,CAAA;AAChB,IAAA,QAAA,CAAA,QAAA,CAAA,eAAA,CAAA,GAAA,CAAA,CAAA,GAAA,eAAiB,CAAA;AACnB,CAAC,EARS,QAAQ,KAAR,QAAQ,GAQjB,EAAA,CAAA,CAAA;;ACXH;;AAEG;AAwBI,MAAM,UAAU,GAAG,CAAC,MAAK;;AAE9B,IAAA,IAAI,SAAc,CAAC;AACnB,IAAA,IAAI,aAAkB,CAAC;;AAEvB,IAAA,IAAI,iBAAsB,CAAC;IAC3B,IAAI,aAAa,GAAyB,IAAI,CAAC;IAE/C,IAAI;AACF,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;;YAEjC,IAAI;gBACF,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AACnC,gBAAA,aAAa,GAAG,IAAI,KAAK,CAAC,2CAA2C,EAAE;AACrE,oBAAA,WAAW,EAAE,UAAU;AACxB,iBAAA,CAAkB,CAAC;AAEpB,gBAAA,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC;AAC3C,gBAAA,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC;;;;;;;;;gBASnD,iBAAiB,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;AAClE,aAAA;AAAC,YAAA,OAAO,UAAU,EAAE;;gBAEnB,IAAI;AACF,oBAAA,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;oBAClF,SAAS,GAAG,SAAS,CAAC;oBACtB,aAAa,GAAG,aAAa,CAAC;;;;;;;;;;AAU9B,oBAAA,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAE,CAAC;oBAC/C,iBAAiB,GAAG,cAAc,CAAC;AACpC,iBAAA;AAAC,gBAAA,OAAO,WAAW,EAAE;AACpB,oBAAA,MAAM,IAAI,QAAQ,CAAC,CAAA,oFAAA,CAAsF,CAAC,CAAC;AAC5G,iBAAA;AACF,aAAA;AACF,SAAA;AAAM,aAAA;;AAEL,YAAA,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;AACrB,gBAAA,MAAM,IAAI,QAAQ,CAAC,gDAAgD,CAAC,CAAC;AACtE,aAAA;AAED,YAAA,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;AACzB,gBAAA,MAAM,IAAI,QAAQ,CAAC,oDAAoD,CAAC,CAAC;AAC1E,aAAA;AAED,YAAA,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;AAC7B,YAAA,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;;;;;;;;;AASrC,YAAA,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC;AAC7C,SAAA;AACF,KAAA;AAAC,IAAA,OAAO,KAAK,EAAE;QACd,MAAM,IAAI,QAAQ,CAAC,CAAA,uCAAA,EAA0C,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AACxH,KAAA;IAED,OAAO;QACL,YAAY,EAAE,MAAK;YACjB,IAAI;gBACF,OAAO,IAAI,SAAS,EAAE,CAAC;AACxB,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,6BAAA,EAAgC,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC9G,aAAA;SACF;QAED,gBAAgB,EAAE,MAAK;YACrB,IAAI;gBACF,OAAO,IAAI,aAAa,EAAE,CAAC;AAC5B,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,iCAAA,EAAoC,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAClH,aAAA;SACF;QAED,QAAQ;AAER,QAAA,eAAe,EAAE,CAAC,SAAiB,EAAE,WAAsB,GAAA,UAAU,KAAI;YACvE,IAAI;AACF,gBAAA,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;gBAC/B,OAAO,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;AACvD,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,qBAAA,EAAwB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AACtG,aAAA;SACF;AAED,QAAA,iBAAiB,EAAE,CAAC,IAAU,KAAI;YAChC,IAAI;AACF,gBAAA,MAAM,UAAU,GAAG,IAAI,aAAa,EAAE,CAAC;AACvC,gBAAA,OAAO,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAC3C,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,yBAAA,EAA4B,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC1G,aAAA;SACF;QAED,cAAc,EAAE,MAAK;YACnB,IAAI;;AAEF,gBAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,oBAAA,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;oBAC/B,OAAO,MAAM,CAAC,eAAe,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;AAC5D,iBAAA;AAAM,qBAAA;oBACL,OAAO,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC3D,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,2BAAA,EAA8B,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC5G,aAAA;SACF;AAED,QAAA,aAAa,EAAE,CAAC,OAAe,KAAI;YACjC,IAAI;AACF,gBAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,oBAAA,OAAO,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AACxC,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/D,oBAAA,OAAO,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AACnC,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,0BAAA,EAA6B,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC3G,aAAA;SACF;AAED,QAAA,eAAe,EAAE,CAAC,YAAoB,EAAE,aAAqB,KAAI;YAC/D,IAAI;AACF,gBAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;oBACjC,OAAO,QAAQ,CAAC,eAAe,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AAC9D,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;oBAC/D,OAAO,GAAG,CAAC,eAAe,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AACzD,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,yCAAA,EAA4C,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC1H,aAAA;SACF;AAED,QAAA,cAAc,EAAE,CAAC,IAAY,KAAI;YAC/B,IAAI;AACF,gBAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,oBAAA,OAAO,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACtC,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/D,oBAAA,OAAO,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACjC,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,4BAAA,EAA+B,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC7G,aAAA;SACF;AAED,QAAA,kBAAkB,EAAE,CAAC,IAAY,KAAI;YACnC,IAAI;;AAEF,gBAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,oBAAA,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACrE,oBAAA,OAAO,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;AACrC,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/D,oBAAA,OAAO,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;AACrC,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,gCAAA,EAAmC,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AACjH,aAAA;SACF;AAED,QAAA,aAAa,EAAE,CAAC,IAAY,KAAI;YAC9B,IAAI;AACF,gBAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,oBAAA,OAAO,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AACrC,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/D,oBAAA,OAAO,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAChC,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,0BAAA,EAA6B,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC3G,aAAA;SACF;AAED,QAAA,2BAA2B,EAAE,CAAC,MAAc,EAAE,IAAY,KAAI;YAC5D,IAAI;AACF,gBAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,oBAAA,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;oBACrE,OAAO,GAAG,CAAC,2BAA2B,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACtD,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;oBAC/D,OAAO,GAAG,CAAC,2BAA2B,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACtD,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,yCAAA,EAA4C,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC1H,aAAA;SACF;;AAID;;AAEG;QACH,sBAAsB,EAAE,CAAC,OAAgB,EAAE,YAA2B,EAAE,aAAqB,EAAE,KAAa,KAAU;YACpH,IAAI;AACF,gBAAA,IAAI,YAAY,EAAE;oBAChB,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAC5D,iBAAA;AAAM,qBAAA;AACL,oBAAA,OAAO,CAAC,YAAY,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;AAC5C,iBAAA;AACF,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,QAAQ,CAAC,CAAA,yBAAA,EAA4B,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAE,CAAA,CAAC,CAAC;AAC1G,aAAA;SACF;AAED;;AAEG;AACH,QAAA,MAAM,EAAE,CAAC,GAAQ,KAAa;YAC5B,IAAI;AACF,gBAAA,OAAO,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;AAC3E,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;AACd,gBAAA,OAAO,KAAK,CAAC;AACd,aAAA;SACF;AAED;;AAEG;AACH,QAAA,eAAe,EAAE,CAAC,QAAgB,KAAY;AAC5C,YAAA,QAAQ,QAAQ;AACd,gBAAA,KAAK,QAAQ,CAAC,YAAY,EAAE,OAAO,cAAc,CAAC;AAClD,gBAAA,KAAK,QAAQ,CAAC,SAAS,EAAE,OAAO,WAAW,CAAC;AAC5C,gBAAA,KAAK,QAAQ,CAAC,kBAAkB,EAAE,OAAO,oBAAoB,CAAC;AAC9D,gBAAA,KAAK,QAAQ,CAAC,YAAY,EAAE,OAAO,cAAc,CAAC;AAClD,gBAAA,KAAK,QAAQ,CAAC,2BAA2B,EAAE,OAAO,6BAA6B,CAAC;AAChF,gBAAA,SAAS,OAAO,CAAqB,kBAAA,EAAA,QAAQ,GAAG,CAAC;AAClD,aAAA;SACF;AAED;;AAEG;AACH,QAAA,iBAAiB,EAAE,CAAC,IAAa,KAA4B;YAC3D,MAAM,MAAM,GAA2B,EAAE,CAAC;AAC1C,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAChC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;AAChC,aAAA;AACD,YAAA,OAAO,MAAM,CAAC;SACf;;QAGD,OAAO,EAAE,MAAK;YACZ,IAAI,aAAa,IAAI,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE;AACrE,gBAAA,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;AAC9B,aAAA;SACF;KACF,CAAC;AACJ,CAAC,GAAG;;MChSS,QAAQ,CAAA;AAGnB;;;AAGG;AACH,IAAA,WAAA,CAAY,MAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;KACtB;AAED;;;;;;;;AAQG;AACH,IAAA,OAAO,CACL,GAAwB,EACxB,IAAY,EACZ,QAAoB,EAAA;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,OAAO,GAAQ,GAAG,CAAC;AAEvB,QAAA,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AAC9B,YAAA,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;;gBAE1B,MAAM,OAAO,GAAG,OAAO;AACpB,qBAAA,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACjD,qBAAA,IAAI,EAAE;qBACN,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC,CAAC;AAClC,gBAAA,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,OAAO,GAAG,SAAS,CAAC;AACpD,aAAA;AAAM,iBAAA;gBACL,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACjD,aAAA;YAED,IAAI,OAAO,KAAK,SAAS;AAAE,gBAAA,OAAO,QAAQ,CAAC;AAC5C,SAAA;;AAGD,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;AAClD,YAAA,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACnB,SAAA;QAED,OAAO,OAAO,KAAK,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;KACnD;AAED;;;;;;;AAOG;IACK,cAAc,CAAC,GAAQ,EAAE,OAAe,EAAA;AAC9C,QAAA,IAAI,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,YAAA,OAAO,SAAS,CAAC;;QAG7D,IAAI,OAAO,IAAI,GAAG,EAAE;AAClB,YAAA,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;AACrB,SAAA;;QAGD,IACE,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK;AACvC,YAAA,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ;AAC1C,YAAA,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU;AAC5C,YAAA,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS;AAC3C,YAAA,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM;AACxC,YAAA,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK;AACvC,YAAA,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ;AAC1C,YAAA,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW;YAC7C,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EACxC;AACA,YAAA,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAC1D,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,KAAK,KAAK,OAAO,CAClC,GAAG,CAAC,CAAC,CAAC;YAEP,IAAI,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE;AAC3C,gBAAA,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;AACrB,aAAA;AACF,SAAA;;QAGD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;AACnD,QAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC;AAClC,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC3B,MAAM,OAAO,GAAG,QAAQ;iBACrB,GAAG,CAAC,CAAC,KAAK,MAAM,OAAO,IAAI,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;iBAC/D,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC,CAAC;AAClC,YAAA,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,OAAO,GAAG,SAAS,CAAC;AACjD,SAAA;AAED,QAAA,OAAO,SAAS,CAAC;KAClB;AAED;;;;;;;AAOG;IACH,WAAW,CAAC,GAAQ,EAAE,IAAU,EAAA;QAC9B,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAE3C,QAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;;AAE5B,YAAA,OAAO,EAAE,CAAC,IAAI,GAAG,aAAa,EAAE,CAAC;AAClC,SAAA;AAED,QAAA,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;;YAEpC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC;AACxC,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AACxD,YAAA,MAAM,aAAa,GAAG,MAAM,GAAG,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,WAAW,CAAE,CAAA,GAAG,WAAW,CAAC;AAExE,YAAA,MAAM,MAAM,GAAQ;gBAClB,CAAC,aAAa,GAAG,EAAE;aACpB,CAAC;;YAGF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;AAClD,YAAA,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE;gBACnD,MAAM,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;AAClD,aAAA;;YAGD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;AACnD,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;AAC5D,YAAA,MAAM,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,GAAG;AACnC,gBAAA,GAAG,QAAQ;AACX,gBAAA,EAAE,CAAC,WAAW,GAAG,aAAa,EAAE;aACjC,CAAC;;YAGF,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;AAC9C,YAAA,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE;gBACf,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5C,aAAA;AAED,YAAA,IAAI,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE;AACzB,gBAAA,MAAM,CAAC,aAAa,CAAC,CAAC,CAAS,MAAA,EAAA,MAAM,CAAE,CAAA,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;AACxD,aAAA;AAED,YAAA,OAAO,MAAM,CAAC;AACf,SAAA;;AAGD,QAAA,OAAO,aAAa,CAAC;KACtB;AAED;;;;AAIG;AACK,IAAA,UAAU,CAAC,KAAU,EAAA;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;QAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;QAEnD,IACE,KAAK,KAAK,IAAI;YACd,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,SAAS,EAC1B;AACA,YAAA,OAAO,EAAE,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;AAC5B,SAAA;AAED,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;;YAExB,OAAO;gBACL,CAAC,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AAChC,oBAAA,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC/B,iBAAC,CAAC;aACH,CAAC;AACH,SAAA;AAED,QAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;;YAE7B,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM;gBAC1D,CAAC,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;AAC5B,aAAA,CAAC,CAAC,CAAC;AAEJ,YAAA,OAAO,EAAE,CAAC,WAAW,GAAG,QAAQ,EAAE,CAAC;AACpC,SAAA;QAED,OAAO,SAAS,CAAC;KAClB;AAED;;;;AAIG;AACH,IAAA,OAAO,CAAC,KAAU,EAAA;QAChB,IAAI,KAAK,IAAI,IAAI;AAAE,YAAA,OAAO,IAAI,CAAC;AAC/B,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;QACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACtE,QAAA,OAAO,KAAK,CAAC;KACd;AAED;;;;;AAKG;AACH,IAAA,aAAa,CAAC,GAAQ,EAAE,MAAA,GAAiB,CAAC,EAAA;QACxC,IAAI;YACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1C,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,2BAA2B,CAAC;AACpC,SAAA;KACF;AAED;;;;AAIG;AACH,IAAA,SAAS,CAAC,GAAQ,EAAA;QAChB,IAAI;YACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;AACxC,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,KAAK,CACb,CAAA,6BAAA,EACE,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CACvD,CAAE,CAAA,CACH,CAAC;AACH,SAAA;KACF;AAED;;;;;AAKG;IACH,SAAS,CAAI,MAAS,EAAE,MAAkB,EAAA;QACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE;AAC5D,YAAA,OAAO,MAAM,CAAC;AACf,SAAA;QAED,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE;AAC5D,YAAA,OAAO,MAAsB,CAAC;AAC/B,SAAA;QAED,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;AAClC,YAAA,MAAM,WAAW,GAAG,MAAM,CAAC,GAAuB,CAAC,CAAC;AACpD,YAAA,MAAM,WAAW,GAAG,MAAM,CAAC,GAAc,CAAC,CAAC;;YAG3C,IACE,WAAW,KAAK,IAAI;AACpB,gBAAA,WAAW,KAAK,IAAI;gBACpB,OAAO,WAAW,KAAK,QAAQ;gBAC/B,OAAO,WAAW,KAAK,QAAQ;AAC/B,gBAAA,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;AAC3B,gBAAA,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAC3B;;AAEC,gBAAA,MAAc,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,WAAkB,CAAC,CAAC;AACxE,aAAA;AAAM,iBAAA;;AAEJ,gBAAA,MAAc,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;AACpC,aAAA;AACH,SAAC,CAAC,CAAC;AAEH,QAAA,OAAO,MAAM,CAAC;KACf;AAED;;;AAGG;IACH,kBAAkB,GAAA;QAChB,IAAI;AACF,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;YACxC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,IAAI,KAAK,CAAC;AAC3D,YAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;AAC1D,YAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC;AACtD,YAAA,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;AAChD,YAAA,MAAM,uBAAuB,GAAG,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC;AACpE,YAAA,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;AACxD,YAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;AAC1D,YAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;;YAG1D,MAAM,aAAa,GAAa,EAAE,CAAC;YAEnC,IAAI,CAAC,OAAO,EAAE;;AAEZ,gBAAA,IAAI,kBAAkB;AAAE,oBAAA,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAEjE,gBAAA,IAAI,aAAa;AAAE,oBAAA,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACvD,gBAAA,IAAI,gBAAgB;AAAE,oBAAA,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC7D,gBAAA,IAAI,uBAAuB;AAAE,oBAAA,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;AACvE,gBAAA,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEvC,gBAAA,IAAI,iBAAiB,EAAE;AACrB,oBAAA,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAEpC,oBAAA,IAAI,kBAAkB,EAAE;AACtB,wBAAA,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;;AAEzC,qBAAA;AACF,iBAAA;AACF,aAAA;;YAGD,MAAM,iBAAiB,GAAwB,EAAE,CAAC;;AAGlD,YAAA,IAAI,kBAAkB,EAAE;AACtB,gBAAA,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG;AACvC,oBAAA,WAAW,EAAE,8BAA8B;AAC3C,oBAAA,IAAI,EAAE,QAAQ;iBACf,CAAC;;AAGF,gBAAA,iBAAiB,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;AACpC,oBAAA,WAAW,EAAE,iCAAiC;AAC9C,oBAAA,IAAI,EAAE,QAAQ;iBACf,CAAC;AACH,aAAA;;AAGD,YAAA,IAAI,iBAAiB,EAAE;AACrB,gBAAA,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG;AACnC,oBAAA,WAAW,EAAE,6BAA6B;AAC1C,oBAAA,IAAI,EAAE,QAAQ;iBACf,CAAC;AACH,aAAA;;AAGD,YAAA,IAAI,kBAAkB,EAAE;AACtB,gBAAA,iBAAiB,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG;AACxC,oBAAA,WAAW,EAAE,oBAAoB;AACjC,oBAAA,IAAI,EAAE,OAAO;AACb,oBAAA,KAAK,EAAE;AACL,wBAAA,IAAI,EAAE,QAAQ;AACd,wBAAA,iBAAiB,EAAE;AACjB,4BAAA,MAAM,EAAE;AACN,gCAAA,IAAI,EAAE,QAAQ;AACd,gCAAA,UAAU,EAAE;AACV,oCAAA,CAAC,SAAS,CAAC,KAAK,GAAG;AACjB,wCAAA,WAAW,EAAE,iBAAiB;AAC9B,wCAAA,IAAI,EAAE,QAAQ;AACf,qCAAA;AACF,iCAAA;AACD,gCAAA,QAAQ,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;AAC5B,6BAAA;AACF,yBAAA;AACD,wBAAA,oBAAoB,EAAE,KAAK;AAC5B,qBAAA;iBACF,CAAC;;AAGF,gBAAA,IAAI,kBAAkB,EAAE;AACtB,oBAAA,MAAM,SAAS,GACb,iBAAiB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAC7D,MAAM,CACP,CAAC,UAAU,CAAC;AAEf,oBAAA,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG;AAC/B,wBAAA,WAAW,EAAE,gCAAgC;AAC7C,wBAAA,IAAI,EAAE,QAAQ;qBACf,CAAC;AAEF,oBAAA,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;AAC5B,wBAAA,WAAW,EAAE,mCAAmC;AAChD,wBAAA,IAAI,EAAE,QAAQ;qBACf,CAAC;AACH,iBAAA;AACF,aAAA;;AAGD,YAAA,IAAI,aAAa,EAAE;AACjB,gBAAA,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG;AACnC,oBAAA,WAAW,EAAE,uBAAuB;AACpC,oBAAA,IAAI,EAAE,QAAQ;iBACf,CAAC;AACH,aAAA;;AAGD,YAAA,IAAI,gBAAgB,EAAE;AACpB,gBAAA,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG;AACtC,oBAAA,WAAW,EAAE,iBAAiB;AAC9B,oBAAA,IAAI,EAAE,QAAQ;iBACf,CAAC;AACH,aAAA;;AAGD,YAAA,IAAI,uBAAuB,EAAE;AAC3B,gBAAA,iBAAiB,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG;AACzC,oBAAA,WAAW,EAAE,wBAAwB;AACrC,oBAAA,IAAI,EAAE,QAAQ;AACd,oBAAA,UAAU,EAAE;AACV,wBAAA,CAAC,SAAS,CAAC,MAAM,GAAG;AAClB,4BAAA,WAAW,EAAE,+BAA+B;AAC5C,4BAAA,IAAI,EAAE,QAAQ;AACf,yBAAA;AACD,wBAAA,CAAC,SAAS,CAAC,KAAK,GAAG;AACjB,4BAAA,WAAW,EAAE,gCAAgC;AAC7C,4BAAA,IAAI,EAAE,QAAQ;AACf,yBAAA;AACF,qBAAA;AACD,oBAAA,QAAQ,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC;iBAC7B,CAAC;AACH,aAAA;;AAGD,YAAA,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG;AACtC,gBAAA,WAAW,EAAE,gBAAgB;AAC7B,gBAAA,IAAI,EAAE,OAAO;AACb,gBAAA,KAAK,EAAE;AACL,oBAAA,IAAI,EAAE,QAAQ;AACd,oBAAA,iBAAiB,EAAE;AACjB,wBAAA,MAAM,EAAE;AACN,4BAAA,IAAI,EAAE,uBAAuB;AAC9B,yBAAA;AACF,qBAAA;AACD,oBAAA,oBAAoB,EAAE,KAAK;AAC5B,iBAAA;aACF,CAAC;;AAGF,YAAA,MAAM,iBAAiB,GAAG;AACxB,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,UAAU,EAAE,iBAAiB;AAC7B,gBAAA,QAAQ,EAAE,aAAa;AACvB,gBAAA,oBAAoB,EAAE,KAAK;aAC5B,CAAC;;AAGF,YAAA,MAAM,MAAM,GAAG;AACb,gBAAA,OAAO,EAAE,8CAA8C;AACvD,gBAAA,KAAK,EAAE,iBAAiB;AACxB,gBAAA,WAAW,EACT,uEAAuE;AACzE,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,iBAAiB,EAAE;AACjB,oBAAA,MAAM,EAAE;AACN,wBAAA,IAAI,EAAE,uBAAuB;AAC9B,qBAAA;AACF,iBAAA;AACD,gBAAA,oBAAoB,EAAE,KAAK;AAC3B,gBAAA,WAAW,EAAE;AACX,oBAAA,OAAO,EAAE,iBAAiB;AAC3B,iBAAA;aACF,CAAC;AAEF,YAAA,OAAO,MAAM,CAAC;AACf,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,KAAK,CACb,CAAA,0BAAA,EACE,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CACvD,CAAE,CAAA,CACH,CAAC;AACH,SAAA;KACF;AAED;;;;AAIG;IACH,eAAe,CAAC,WAAmB,MAAM,EAAA;AACvC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;AACxC,QAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;AAC1D,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC;AACtD,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;AAChD,QAAA,MAAM,uBAAuB,GAAG,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC;AACpE,QAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;;AAG1D,QAAA,MAAM,OAAO,GAAwB;YACnC,CAAC,QAAQ,GAAG;AACV,gBAAA,CAAC,SAAS,CAAC,KAAK,GAAG,cAAc;AACjC,gBAAA,CAAC,SAAS,CAAC,QAAQ,GAAG;AACpB,oBAAA;AACE,wBAAA,KAAK,EAAE;AACL,4BAAA,CAAC,SAAS,CAAC,KAAK,GAAG,eAAe;AACnC,yBAAA;AACF,qBAAA;AACF,iBAAA;AACF,aAAA;SACF,CAAC;;AAGF,QAAA,IAAI,kBAAkB,EAAE;YACtB,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC;YACjE,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAC3C,YAAA,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC;AACjE,gBAAA,uBAAuB,CAAC;YAC1B,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AACzE,SAAA;;AAGD,QAAA,IAAI,kBAAkB,EAAE;YACtB,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG;gBACxC,EAAE,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,GAAG,QAAQ,EAAE,EAAE;gBACvC,EAAE,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,GAAG,IAAI,EAAE,EAAE;aACtC,CAAC;AAEF,YAAA,IAAI,kBAAkB,EAAE;AACtB,gBAAA,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;AAC/D,oBAAA,KAAK,CAAC;AACT,aAAA;AAED,YAAA,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG;gBACrE,EAAE,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE;aACzC,CAAC;AACH,SAAA;;AAGD,QAAA,IAAI,aAAa,EAAE;AACjB,YAAA,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG;AACnE,gBAAA,EAAE,CAAC,SAAS,CAAC,KAAK,GAAG,0BAA0B,EAAE;aAClD,CAAC;AACH,SAAA;;AAGD,QAAA,IAAI,gBAAgB,EAAE;YACpB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;gBACvE,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;AACzE,aAAA;YAED,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;AACtE,gBAAA,CAAC,SAAS,CAAC,QAAQ,GAAG,yBAAyB;AAChD,aAAA,CAAC,CAAC;AACJ,SAAA;;AAGD,QAAA,IAAI,uBAAuB,EAAE;YAC3B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;gBAC1C,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;AAC5C,aAAA;YAED,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;AAC5C,gBAAA,CAAC,SAAS,CAAC,WAAW,GAAG;AACvB,oBAAA,CAAC,SAAS,CAAC,MAAM,GAAG,gBAAgB;AACpC,oBAAA,CAAC,SAAS,CAAC,KAAK,GAAG,kCAAkC;AACtD,iBAAA;AACF,aAAA,CAAC,CAAC;AACJ,SAAA;AAED,QAAA,OAAO,OAAO,CAAC;KAChB;AACF;;AC5iBD;;AAEG;MACU,aAAa,CAAA;AAGxB;;;AAGG;AACH,IAAA,WAAA,CAAY,MAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;KACtB;AAED;;;;;AAKG;IACH,eAAe,CAAC,KAAU,EAAE,OAAyB,EAAA;;AAEnD,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE;AAC5E,YAAA,OAAO,KAAK,CAAC;AACd,SAAA;;QAGD,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;YACrD,gBAAgB,GAAG,WAAW,CAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;AACnE,SAAA;AAED,QAAA,OAAO,gBAAgB,CAAC;KACzB;AAED;;;;;;;AAOG;IACH,aAAa,CACX,SAA6B,EAC7B,QAAgB,EAChB,QAAgB,EAChB,UAOI,EAAE,EAAA;QAEN,OAAO;YACL,SAAS;YACT,QAAQ;YACR,QAAQ;AACR,YAAA,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,QAAQ;YAC9B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;AACtB,YAAA,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK;YACzC,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;KACH;AAED;;;;AAIG;AACH,IAAA,eAAe,CAAC,QAAgB,EAAA;AAC9B,QAAA,OAAO,UAAU,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;KAC7C;AACF;;AC3ED;;AAEG;MACU,kBAAkB,CAAA;AAK7B;;;AAGG;AACH,IAAA,WAAA,CAAY,MAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KACrD;AAED;;;;AAIG;AACI,IAAA,OAAO,CAAC,SAAiB,EAAA;QAC9B,IAAI;YACF,MAAM,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;;YAGjE,MAAM,MAAM,GAAG,MAAM,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC;AAC1D,YAAA,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;AACrB,gBAAA,MAAM,IAAI,QAAQ,CAAC,CAAA,mBAAA,EAAsB,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAE,CAAA,CAAC,CAAC;AACnE,aAAA;YAED,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AAChD,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,QAAQ,CAChB,CAAA,+BAAA,EACE,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CACvD,CAAE,CAAA,CACH,CAAC;AACH,SAAA;KACF;AAED;;;;;;AAMG;AACK,IAAA,UAAU,CAAC,IAAU,EAAE,aAAgC,EAAE,OAAe,EAAE,EAAA;QAChF,MAAM,MAAM,GAAwB,EAAE,CAAC;;QAGvC,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC,YAAY,EAAE;YACtD,MAAM,OAAO,GAAG,IAAe,CAAC;;AAEhC,YAAA,MAAM,QAAQ,GACZ,OAAO,CAAC,SAAS;gBACjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE;gBACjC,OAAO,CAAC,QAAQ,CAAC;;AAGnB,YAAA,MAAM,WAAW,GAAG,IAAI,GAAG,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,QAAQ,CAAE,CAAA,GAAG,QAAQ,CAAC;YAE5D,MAAM,OAAO,GAAwB,EAAE,CAAC;;AAGxC,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAC9C,aAAa,EACb,QAAQ,EACR,IAAI,CAAC,QAAQ,EACb;AACE,gBAAA,IAAI,EAAE,WAAW;AACjB,gBAAA,SAAS,EAAE,OAAO,CAAC,YAAY,IAAI,SAAS;AAC5C,gBAAA,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,SAAS;AACnC,gBAAA,MAAM,EAAE,aAAa;AACtB,aAAA,CACF,CAAC;;AAGF,YAAA,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE;AAClC,gBAAA,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;AAChC,gBAAA,IAAI,EAAE,EAAE;oBACN,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;AAC/C,iBAAA;AAED,gBAAA,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;AAC9B,gBAAA,IAAI,MAAM,EAAE;oBACV,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AAChD,iBAAA;AACF,aAAA;;AAGD,YAAA,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;gBACnE,MAAM,KAAK,GAA+B,EAAE,CAAC;AAE7C,gBAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBAClD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;;oBAEnC,MAAM,aAAa,GACjB,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC;;AAG5D,oBAAA,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAClD,aAAa,EACb,QAAQ,EACR,IAAI,CAAC,QAAQ,EACb;AACE,wBAAA,IAAI,EAAE,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,aAAa,CAAE,CAAA;AACvC,wBAAA,SAAS,EAAE,IAAI,CAAC,YAAY,IAAI,SAAS;AACzC,wBAAA,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS;AAChC,wBAAA,WAAW,EAAE,IAAI;AACjB,wBAAA,aAAa,EAAE,aAAa;AAC5B,wBAAA,MAAM,EAAE,OAAO;AAChB,qBAAA,CACF,CAAC;;AAGF,oBAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CACzD,IAAI,CAAC,KAAK,EACV,WAAW,CACZ,CAAC;;AAGF,oBAAA,MAAM,OAAO,GAAwB;wBACnC,CAAC,aAAa,GAAG;4BACf,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,gBAAgB;AAChD,yBAAA;qBACF,CAAC;;AAGF,oBAAA,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE;;wBAElC,IAAI,IAAI,CAAC,YAAY,EAAE;4BACrB,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;gCACrD,IAAI,CAAC,YAAY,CAAC;AACrB,yBAAA;;wBAGD,IAAI,IAAI,CAAC,MAAM,EAAE;4BACf,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;gCAClD,IAAI,CAAC,MAAM,CAAC;AACf,yBAAA;AACF,qBAAA;AAED,oBAAA,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACrB,iBAAA;AAED,gBAAA,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;oBACpB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;AACnD,iBAAA;AACF,aAAA;;AAGD,YAAA,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;gBACjC,MAAM,QAAQ,GAA+B,EAAE,CAAC;gBAChD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;gBACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;gBACnD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC;gBACzD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;AAE/C,gBAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBAClD,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;;oBAGpC,IAAI,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE;AACpD,wBAAA,IAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE;AACjC,4BAAA,IAAI,IAAI,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;;AAGjC,4BAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE;AACnC,gCAAA,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;oCACtB,SAAS;AACV,iCAAA;;AAED,gCAAA,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;AACpB,6BAAA;;AAGD,4BAAA,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAClD,aAAa,EACb,OAAO,EACP,KAAK,CAAC,QAAQ,EACd;gCACE,IAAI,EAAE,CAAG,EAAA,WAAW,CAAQ,MAAA,CAAA;AAC5B,gCAAA,MAAM,EAAE,OAAO;AAChB,6BAAA,CACF,CAAC;;AAGF,4BAAA,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CACxD,IAAI,EACJ,WAAW,CACZ,CAAC;4BAEF,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,GAAG,eAAe,EAAE,CAAC,CAAC;AAChD,yBAAA;AACF,qBAAA;;yBAEI,IACH,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC,kBAAkB;AACzD,wBAAA,IAAI,CAAC,MAAM,CAAC,aAAa,EACzB;;AAEA,wBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CACnD,aAAa,EACb,QAAQ,EACR,KAAK,CAAC,QAAQ,EACd;4BACE,IAAI,EAAE,CAAG,EAAA,WAAW,CAAS,OAAA,CAAA;AAC7B,4BAAA,MAAM,EAAE,OAAO;AAChB,yBAAA,CACF,CAAC;;AAGF,wBAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CACzD,KAAK,CAAC,SAAS,IAAI,EAAE,EACrB,YAAY,CACb,CAAC;wBAEF,QAAQ,CAAC,IAAI,CAAC;4BACZ,CAAC,QAAQ,GAAG,gBAAgB;AAC7B,yBAAA,CAAC,CAAC;AACJ,qBAAA;;yBAEI,IACH,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC,YAAY;AACnD,wBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAC5B;wBACA,QAAQ,CAAC,IAAI,CAAC;AACZ,4BAAA,CAAC,WAAW,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE;AACrC,yBAAA,CAAC,CAAC;AACJ,qBAAA;;yBAEI,IACH,KAAK,CAAC,QAAQ;wBACZ,UAAU,CAAC,QAAQ,CAAC,2BAA2B;AACjD,wBAAA,IAAI,CAAC,MAAM,CAAC,uBAAuB,EACnC;wBACA,QAAQ,CAAC,IAAI,CAAC;4BACZ,CAAC,cAAc,GAAG;AAChB,gCAAA,CAAC,SAAS,GAAG,KAAK,CAAC,QAAQ;AAC3B,gCAAA,CAAC,QAAQ,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE;AAClC,6BAAA;AACF,yBAAA,CAAC,CAAC;AACJ,qBAAA;;yBAEI,IAAI,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC,YAAY,EAAE;AAC5D,wBAAA,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;AAC7D,qBAAA;AACF,iBAAA;AAED,gBAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;AACvB,oBAAA,OAAO,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC;AACjC,iBAAA;AACF,aAAA;;AAGD,YAAA,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE;gBACrC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;oBACnC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;oBAC7C,IAAI,OAAO,KAAK,SAAS,EAAE;AACzB,wBAAA,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACrB,qBAAA;AAAM,yBAAA;AACL,wBAAA,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;AACxB,qBAAA;AACH,iBAAC,CAAC,CAAC;AACJ,aAAA;AAED,YAAA,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC;AAC5B,SAAA;AAED,QAAA,OAAO,MAAM,CAAC;KACf;AAEO,IAAA,SAAS,CAAC,IAAS,EAAA;AACzB,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;;YAEvB,MAAM,YAAY,GAAG,IAAI;AACtB,iBAAA,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACnC,iBAAA,MAAM,CAAC,CAAC,IAAI,KAAI;AACf,gBAAA,OAAO,EACL,IAAI,KAAK,IAAI;AACb,oBAAA,IAAI,KAAK,SAAS;AAClB,qBAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAC7D,CAAC;AACJ,aAAC,CAAC,CAAC;AACL,YAAA,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,GAAG,YAAY,GAAG,SAAS,CAAC;AAC3D,SAAA;aAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE;;YAEpD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;gBAChC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC/C,IACE,YAAY,KAAK,IAAI;AACrB,oBAAA,YAAY,KAAK,SAAS;AAC1B,qBAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC;qBACzD,OAAO,YAAY,KAAK,QAAQ;wBAC/B,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EACzC;AACA,oBAAA,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAClB,iBAAA;AAAM,qBAAA;AACL,oBAAA,IAAI,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;AAC1B,iBAAA;AACH,aAAC,CAAC,CAAC;;YAGH,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/B,YAAA,IACE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,QAAQ,CAAC;AAC5D,iBAAC,IAAI,CAAC,WAAW,CAAC,KAAK,SAAS;oBAC9B,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;AAC3C,iBAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EACvE;AACA,gBAAA,OAAO,SAAS,CAAC;AAClB,aAAA;AAED,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AACxD,SAAA;AAED,QAAA,OAAO,IAAI,CAAC;KACb;AACF;;AChVD;;AAEG;MAKU,OAAO,CAAA;AAGlB;;;AAGG;AACH,IAAA,WAAA,CAAY,MAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;KACtB;AAED;;;;AAIG;AACH,IAAA,cAAc,CAAC,SAAiB,EAAA;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC;QAChD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAElC,IAAI;YACF,MAAM,GAAG,GAAG,UAAU,CAAC,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAE9D,MAAM,UAAU,GAAG,CAAC,IAAU,EAAE,KAAK,GAAG,CAAC,KAAY;gBACnD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAEjC,QAAQ,IAAI,CAAC,QAAQ;AACnB,oBAAA,KAAK,UAAU,CAAC,QAAQ,CAAC,YAAY,EAAE;wBACrC,MAAM,EAAE,GAAG,IAAe,CAAC;AAC3B,wBAAA,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC;wBAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC;AACpC,6BAAA,GAAG,CAAC,CAAC,CAAC,KAAK,CAAA,EAAG,CAAC,CAAC,IAAI,CAAK,EAAA,EAAA,CAAC,CAAC,KAAK,GAAG,CAAC;6BACpC,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,wBAAA,MAAM,OAAO,GAAG,KAAK,GAAG,CAAI,CAAA,EAAA,OAAO,CAAI,CAAA,EAAA,KAAK,GAAG,GAAG,CAAI,CAAA,EAAA,OAAO,GAAG,CAAC;wBAEjE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;AAE3C,wBAAA,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;AACzB,4BAAA,OAAO,CAAG,EAAA,GAAG,CAAG,EAAA,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA,EAAA,CAAI,CAAC;AAClD,yBAAA;;AAGD,wBAAA,IACE,QAAQ,CAAC,MAAM,KAAK,CAAC;AACrB,6BAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;gCACpB,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC,SAAS;gCACtD,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EACzC;;AAEA,4BAAA,OAAO,GAAG,GAAG,CAAA,CAAA,EAAI,OAAO,CAAG,EAAA,KAAK,GAAG,GAAG,GAAG,KAAK,GAAG,EAAE,CAAM,GAAA,EAAA,OAAO,KAAK,CAAC;AACvE,yBAAA;wBAED,MAAM,KAAK,GAAG,QAAQ;AACnB,6BAAA,GAAG,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;6BAC5C,IAAI,CAAC,EAAE,CAAC,CAAC;wBACZ,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,OAAO,CAAA,EAAA,EAAK,KAAK,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,OAAO,CAAA,GAAA,CAAK,CAAC;AAC1D,qBAAA;AAED,oBAAA,KAAK,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE;wBAClC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;AACtC,wBAAA,OAAO,IAAI,GAAG,CAAG,EAAA,GAAG,CAAG,EAAA,IAAI,CAAI,EAAA,CAAA,GAAG,EAAE,CAAC;AACtC,qBAAA;AAED,oBAAA,KAAK,UAAU,CAAC,QAAQ,CAAC,kBAAkB;AACzC,wBAAA,OAAO,GAAG,GAAG,CAAA,SAAA,EAAY,IAAI,CAAC,SAAS,OAAO,CAAC;AAEjD,oBAAA,KAAK,UAAU,CAAC,QAAQ,CAAC,YAAY;AACnC,wBAAA,OAAO,GAAG,GAAG,CAAA,IAAA,EAAO,IAAI,CAAC,SAAS,OAAO,CAAC;AAE5C,oBAAA,KAAK,UAAU,CAAC,QAAQ,CAAC,2BAA2B;wBAClD,MAAM,EAAE,GAAG,IAA6B,CAAC;wBACzC,OAAO,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,EAAE,CAAC,MAAM,CAAA,CAAA,EAAI,EAAE,CAAC,IAAI,CAAA,IAAA,CAAM,CAAC;AAE/C,oBAAA,KAAK,UAAU,CAAC,QAAQ,CAAC,aAAa;AACpC,wBAAA,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;AAC/B,6BAAA,GAAG,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;6BACxC,IAAI,CAAC,EAAE,CAAC,CAAC;AAEd,oBAAA;AACE,wBAAA,OAAO,EAAE,CAAC;AACb,iBAAA;AACH,aAAC,CAAC;AAEF,YAAA,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/B,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,QAAQ,CAChB,CAAA,4BAAA,EACE,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CACvD,CAAE,CAAA,CACH,CAAC;AACH,SAAA;KACF;AAED;;;;AAIG;AACH,IAAA,WAAW,CAAC,SAAiB,EAAA;QAI3B,IAAI;YACF,MAAM,GAAG,GAAG,UAAU,CAAC,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,GAAG,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC;AACvD,YAAA,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;gBACrB,OAAO;AACL,oBAAA,OAAO,EAAE,KAAK;oBACd,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,uBAAuB;iBAC1D,CAAC;AACH,aAAA;AACD,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1B,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;YACd,OAAO;AACL,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,OAAO,EAAE,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;aAChE,CAAC;AACH,SAAA;KACF;AAED;;;;AAIG;AACH,IAAA,oBAAoB,CAAC,SAAiB,EAAA;QACpC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE;YACzC,OAAO,0CAA0C,GAAG,SAAS,CAAC;AAC/D,SAAA;AACD,QAAA,OAAO,SAAS,CAAC;KAClB;AAED;;;;AAIG;AACH,IAAA,SAAS,CAAC,IAAY,EAAA;QACpB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AACjD,YAAA,OAAO,EAAE,CAAC;AACX,SAAA;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,KAAI;AACvC,YAAA,QAAQ,IAAI;AACV,gBAAA,KAAK,GAAG;AACN,oBAAA,OAAO,OAAO,CAAC;AACjB,gBAAA,KAAK,GAAG;AACN,oBAAA,OAAO,MAAM,CAAC;AAChB,gBAAA,KAAK,GAAG;AACN,oBAAA,OAAO,MAAM,CAAC;AAChB,gBAAA,KAAK,GAAG;AACN,oBAAA,OAAO,QAAQ,CAAC;AAClB,gBAAA,KAAK,GAAG;AACN,oBAAA,OAAO,QAAQ,CAAC;AAClB,gBAAA;AACE,oBAAA,OAAO,IAAI,CAAC;AACf,aAAA;AACH,SAAC,CAAC,CAAC;KACJ;AAED;;;;AAIG;AACH,IAAA,WAAW,CAAC,IAAY,EAAA;QACtB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AACjD,YAAA,OAAO,EAAE,CAAC;AACX,SAAA;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,0BAA0B,EAAE,CAAC,KAAK,EAAE,MAAM,KAAI;AAChE,YAAA,QAAQ,MAAM;AACZ,gBAAA,KAAK,KAAK;AACR,oBAAA,OAAO,GAAG,CAAC;AACb,gBAAA,KAAK,IAAI;AACP,oBAAA,OAAO,GAAG,CAAC;AACb,gBAAA,KAAK,IAAI;AACP,oBAAA,OAAO,GAAG,CAAC;AACb,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,GAAG,CAAC;AACb,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,GAAG,CAAC;AACb,gBAAA;AACE,oBAAA,OAAO,KAAK,CAAC;AAChB,aAAA;AACH,SAAC,CAAC,CAAC;KACJ;AAED;;;;AAIG;AACH,IAAA,aAAa,CAAC,aAAqB,EAAA;QACjC,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC9C,QAAA,OAAO,UAAU,GAAG,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC;KACvE;AAED;;;;AAIG;AACH,IAAA,gBAAgB,CAAC,aAAqB,EAAA;QACpC,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,OAAO,UAAU,GAAG,CAAC;cACjB,aAAa,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC;cACvC,aAAa,CAAC;KACnB;AAED;;;;;AAKG;IACH,mBAAmB,CAAC,MAAqB,EAAE,SAAiB,EAAA;AAC1D,QAAA,OAAO,MAAM,GAAG,CAAG,EAAA,MAAM,CAAI,CAAA,EAAA,SAAS,CAAE,CAAA,GAAG,SAAS,CAAC;KACtD;AACF;;ACxND;;AAEG;MACU,kBAAkB,CAAA;AAK7B;;;AAGG;AACH,IAAA,WAAA,CAAY,MAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KACrD;AAED;;;;AAIG;AACI,IAAA,OAAO,CAAC,OAA4B,EAAA;QACzC,IAAI;AACF,YAAA,MAAM,GAAG,GAAG,UAAU,CAAC,cAAc,EAAE,CAAC;YACxC,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAElD,YAAA,IAAI,WAAW,EAAE;;gBAEf,IAAI,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,eAAe,CAAC,QAAQ,KAAK,MAAM,EAAE;oBAClE,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,iBAAA;AAAM,qBAAA;AACL,oBAAA,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;AAC9B,iBAAA;AACF,aAAA;;YAGD,IAAI,SAAS,GAAG,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;;YAGlD,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,uCAAuC,EAAE,EAAE,CAAC,CAAC;YAE3E,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE;gBAC7C,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;AAC1D,aAAA;;AAGD,YAAA,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE;gBACzC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;AACpD,aAAA;AAED,YAAA,OAAO,SAAS,CAAC;AAClB,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,QAAQ,CAChB,CAAA,+BAAA,EACE,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CACvD,CAAE,CAAA,CACH,CAAC;AACH,SAAA;KACF;AAED;;;;;;;AAOG;IACK,UAAU,CAChB,OAA4B,EAC5B,GAAa,EACb,aAAgC,EAChC,OAAe,EAAE,EAAA;AAEjB,QAAA,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;AAC3C,YAAA,OAAO,IAAI,CAAC;AACb,SAAA;;QAGD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE;AACb,YAAA,OAAO,IAAI,CAAC;AACb,SAAA;AAED,QAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;;AAGnC,QAAA,MAAM,WAAW,GAAG,IAAI,GAAG,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,QAAQ,CAAE,CAAA,GAAG,QAAQ,CAAC;;AAG5D,QAAA,IAAI,OAAgB,CAAC;QACrB,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;AAC/C,QAAA,MAAM,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;AAClC,QAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;;AAGnC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAC9C,aAAa,EACb,QAAQ,EACR,UAAU,CAAC,QAAQ,CAAC,YAAY,EAChC;AACE,YAAA,IAAI,EAAE,WAAW;AACjB,YAAA,SAAS,EAAE,EAAE;AACb,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,MAAM,EAAE,aAAa;AACtB,SAAA,CACF,CAAC;AAEF,QAAA,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE;AACxC,YAAA,IAAI,MAAM,EAAE;;AAEV,gBAAA,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC,EAAE,EAAE,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAC,CAAC;AACnE,aAAA;AAAM,iBAAA;;gBAEL,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;AACpD,aAAA;AACF,SAAA;AAAM,aAAA;;AAEL,YAAA,OAAO,GAAG,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;AAC9C,SAAA;;QAGD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;AAC7C,QAAA,IACE,IAAI,CAAC,MAAM,CAAC,kBAAkB;YAC9B,QAAQ,CAAC,aAAa,CAAC;YACvB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,EACtC;YACA,QAAQ,CAAC,aAAa,CAAC,CAAC,OAAO,CAC7B,CAAC,OAA4B,KAAI;gBAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,gBAAA,IAAI,CAAC,QAAQ;oBAAE,OAAO;AAEtB,gBAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;;AAGnC,gBAAA,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAClD,aAAa,EACb,QAAQ,EACR,UAAU,CAAC,QAAQ,CAAC,YAAY,EAChC;AACE,oBAAA,IAAI,EAAE,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,QAAQ,CAAE,CAAA;AAClC,oBAAA,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC;AACjC,oBAAA,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC;AAC3B,oBAAA,WAAW,EAAE,IAAI;AACjB,oBAAA,aAAa,EAAE,QAAQ;AACvB,oBAAA,MAAM,EAAE,OAAO;AAChB,iBAAA,CACF,CAAC;;AAGF,gBAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CACzD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EACxB,WAAW,CACZ,CAAC;AAEF,gBAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;AACtC,gBAAA,MAAM,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;;gBAGvC,IAAI,aAAa,GAAG,QAAQ,CAAC;AAC7B,gBAAA,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE;AAChD,oBAAA,aAAa,GAAG,CAAG,EAAA,UAAU,CAAI,CAAA,EAAA,QAAQ,EAAE,CAAC;AAC7C,iBAAA;gBAED,UAAU,CAAC,sBAAsB,CAC/B,OAAO,EACP,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,MAAM,GAAG,IAAI,EAC1D,aAAa,EACb,gBAAgB,CACjB,CAAC;AACJ,aAAC,CACF,CAAC;AACH,SAAA;;AAGD,QAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE;;AAEpC,YAAA,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAClD,aAAa,EACb,QAAQ,EACR,UAAU,CAAC,QAAQ,CAAC,SAAS,EAC7B;gBACE,IAAI,EAAE,CAAG,EAAA,WAAW,CAAQ,MAAA,CAAA;AAC5B,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,MAAM,EAAE,MAAM;AACd,gBAAA,MAAM,EAAE,OAAO;AAChB,aAAA,CACF,CAAC;AAEF,YAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CACzD,QAAQ,CAAC,QAAQ,CAAC,EAClB,WAAW,CACZ,CAAC;AAEF,YAAA,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC;AACxC,SAAA;;QAGD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;QAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;QACnD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QAE/C,IACE,QAAQ,CAAC,WAAW,CAAC;YACrB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EACpC;YACA,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,CAC3B,CAAC,KAA0B,KAAI;;AAE7B,gBAAA,IACE,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS;AAC7B,oBAAA,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAC7B;;AAEA,oBAAA,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAClD,aAAa,EACb,OAAO,EACP,UAAU,CAAC,QAAQ,CAAC,SAAS,EAC7B;wBACE,IAAI,EAAE,CAAG,EAAA,WAAW,CAAQ,MAAA,CAAA;AAC5B,wBAAA,MAAM,EAAE,OAAO;AAChB,qBAAA,CACF,CAAC;AAEF,oBAAA,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CACxD,KAAK,CAAC,QAAQ,CAAC,EACf,WAAW,CACZ,CAAC;AAEF,oBAAA,OAAO,CAAC,WAAW,CACjB,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CACnE,CAAC;AACH,iBAAA;;AAEI,qBAAA,IACH,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS;AAC7B,oBAAA,IAAI,CAAC,MAAM,CAAC,aAAa,EACzB;;AAEA,oBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CACnD,aAAa,EACb,QAAQ,EACR,UAAU,CAAC,QAAQ,CAAC,kBAAkB,EACtC;wBACE,IAAI,EAAE,CAAG,EAAA,WAAW,CAAS,OAAA,CAAA;AAC7B,wBAAA,MAAM,EAAE,OAAO;AAChB,qBAAA,CACF,CAAC;AAEF,oBAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CACzD,KAAK,CAAC,QAAQ,CAAC,EACf,YAAY,CACb,CAAC;oBAEF,OAAO,CAAC,WAAW,CACjB,UAAU,CAAC,kBAAkB,CAC3B,gBAAgB,CACjB,CACF,CAAC;AACH,iBAAA;;AAEI,qBAAA,IACH,KAAK,CAAC,WAAW,CAAC,KAAK,SAAS;AAChC,oBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAC5B;AACA,oBAAA,OAAO,CAAC,WAAW,CACjB,UAAU,CAAC,aAAa,CACtB,KAAK,CAAC,WAAW,CAAC,CACnB,CACF,CAAC;AACH,iBAAA;;AAEI,qBAAA,IACH,KAAK,CAAC,cAAc,CAAC,KAAK,SAAS;AACnC,oBAAA,IAAI,CAAC,MAAM,CAAC,uBAAuB,EACnC;AACA,oBAAA,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;AACrC,oBAAA,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;oBACjC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;AAEpC,oBAAA,IAAI,MAAM,EAAE;AACV,wBAAA,OAAO,CAAC,WAAW,CACjB,UAAU,CAAC,2BAA2B,CAAC,MAAM,EAAE,IAAI,CAAC,CACrD,CAAC;AACH,qBAAA;AACF,iBAAA;;AAEI,qBAAA;AACH,oBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;AACvE,oBAAA,IAAI,YAAY,EAAE;AAChB,wBAAA,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;AACnC,qBAAA;AACF,iBAAA;AACH,aAAC,CACF,CAAC;AACH,SAAA;AAED,QAAA,OAAO,OAAO,CAAC;KAChB;AACF;;ACvTD;;AAEG;AACU,MAAA,cAAc,GAAkB;AAC3C,IAAA,kBAAkB,EAAE,IAAI;AACxB,IAAA,gBAAgB,EAAE,IAAI;AACtB,IAAA,uBAAuB,EAAE,IAAI;AAC7B,IAAA,aAAa,EAAE,IAAI;AACnB,IAAA,iBAAiB,EAAE,IAAI;AACvB,IAAA,kBAAkB,EAAE,KAAK;AACzB,IAAA,kBAAkB,EAAE,IAAI;AAExB,IAAA,aAAa,EAAE;AACb,QAAA,WAAW,EAAE,IAAI;AACjB,QAAA,MAAM,EAAE,CAAC;AACT,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,IAAI,EAAE,EAAE;AACR,QAAA,GAAG,EAAE;AACH,YAAA,WAAW,EAAE,IAAI;AAClB,SAAA;AACF,KAAA;AAED,IAAA,SAAS,EAAE;AACT,QAAA,SAAS,EAAE,KAAK;AAChB,QAAA,MAAM,EAAE,MAAM;AACd,QAAA,UAAU,EAAE,OAAO;AACnB,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,QAAQ,EAAE,OAAO;AACjB,QAAA,WAAW,EAAE,KAAK;AAClB,QAAA,MAAM,EAAE,OAAO;AACf,QAAA,QAAQ,EAAE,WAAW;AACtB,KAAA;;;ACrCH;;AAEG;MAUU,GAAG,CAAA;AAOd;;;AAGG;AACH,IAAA,WAAA,CAAY,SAAiC,EAAE,EAAA;;QAE7C,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,cAAc,CAAC,CAAC;;QAG7C,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;;AAG7D,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAgB,YAAY,EAAE,MAAM,CAAC,CAAC;;QAG3E,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;;QAG1C,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,kBAAkB,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,kBAAkB,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KAC/D;AAED;;;;AAIG;AACI,IAAA,SAAS,CAAC,SAAiB,EAAA;QAChC,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;KACnD;AAED;;;;AAIG;AACI,IAAA,SAAS,CAAC,OAA4B,EAAA;QAC3C,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;KACjD;AAED;;;;AAIG;AACI,IAAA,cAAc,CAAC,SAAiB,EAAA;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;KAC/C;AAED;;;;;;AAMG;AACI,IAAA,OAAO,CACZ,GAAwB,EACxB,IAAY,EACZ,WAAgB,SAAS,EAAA;AAEzB,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;KACnD;AAED;;;;AAIG;AACI,IAAA,WAAW,CAAC,SAAiB,EAAA;QAIlC,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;KAC5C;AAED;;;AAGG;IACI,kBAAkB,GAAA;AACvB,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC;KAC3C;AAED;;;;;AAKG;IACI,WAAW,CAAC,GAAQ,EAAE,IAAmC,EAAA;QAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;KAC7C;AAED;;;;AAIG;IACI,mBAAmB,CAAC,WAAmB,MAAM,EAAA;QAClD,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;KAChD;AAED;;;;AAIG;AACI,IAAA,cAAc,CAAC,WAA6B,EAAA;AACjD,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;AAChC,YAAA,IAAI,CAAC,MAAM,CAAC,eAAe,GAAG,EAAE,CAAC;AAClC,SAAA;QACD,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC9C,QAAA,OAAO,IAAI,CAAC;KACb;AAED;;;AAGG;IACI,iBAAiB,GAAA;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,eAAe,GAAG,EAAE,CAAC;AACjC,QAAA,OAAO,IAAI,CAAC;KACb;AAED;;AAEG;IACI,OAAO,GAAA;QACZ,UAAU,CAAC,OAAO,EAAE,CAAC;KACtB;AACF;;ACpHD;;AAEG;MACmB,gBAAgB,CAAA;AACpC;;;;;AAKG;IACH,OAAO,CAAC,KAAU,EAAE,OAAyB,EAAA;AAC3C,QAAA,IAAI,OAAO,CAAC,SAAS,KAAK,aAAa,EAAE;YACvC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACvC,SAAA;AAAM,aAAA;YACL,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACvC,SAAA;KACF;AAED;;;;;AAKG;IACO,SAAS,CAAC,KAAU,EAAE,OAAyB,EAAA;;AAEvD,QAAA,OAAO,KAAK,CAAC;KACd;AAED;;;;;AAKG;IACO,SAAS,CAAC,KAAU,EAAE,OAAyB,EAAA;;AAEvD,QAAA,OAAO,KAAK,CAAC;KACd;AACF;;AC1ED;;;;"} \ No newline at end of file diff --git a/dist/stats.html b/dist/stats.html index 1e4c7be..7568124 100644 --- a/dist/stats.html +++ b/dist/stats.html @@ -4929,7 +4929,7 @@