fast-xml-parser
Advanced tools
Comparing version 3.20.3 to 3.21.0
{ | ||
"name": "fast-xml-parser", | ||
"version": "3.20.3", | ||
"version": "3.21.0", | ||
"description": "Validate XML or Parse XML to JS/JSON very fast without C/C++ based libraries", | ||
"main": "./src/parser.js", | ||
"scripts": { | ||
"test": "jasmine spec/*spec.js", | ||
"test": "npx nyc jasmine spec/*spec.js", | ||
"unit": "jasmine", | ||
"coverage": "npx nyc report --reporter html --reporter text -t .nyc_output --report-dir .nyc_output/summary", | ||
"perf": "node ./benchmark/perfTest3.js", | ||
"lint": "eslint src/*.js spec/*.js", | ||
"bundle": "webpack && webpack --config webpack-prod.config.js", | ||
"coverage": "istanbul cover -x \"cli.js\" -x \"spec/*spec.js\" jasmine spec/*spec.js;", | ||
"coverage:check": "istanbul check-coverage --branch 90 --statement 90", | ||
"prettier": "prettier --write src/**/*.js", | ||
"publish-please": "publish-please", | ||
"prepublishOnly": "publish-please guard" | ||
"checkReadiness": "publish-please --dry-run" | ||
}, | ||
@@ -79,4 +78,2 @@ "bin": { | ||
"he": "^1.2.0", | ||
"http-server": "^0.12.3", | ||
"istanbul": "^0.4.5", | ||
"jasmine": "^3.6.4", | ||
@@ -95,4 +92,5 @@ "nimnjs": "^1.3.2", | ||
"dependencies": { | ||
"nyc": "^15.1.0", | ||
"strnum": "^1.0.4" | ||
} | ||
} |
@@ -26,2 +26,4 @@ | ||
Check [ThankYouBackers](https://github.com/NaturalIntelligence/ThankYouBackers) for our contributors | ||
## Users | ||
@@ -107,9 +109,15 @@ List of some applications/projects using Fast XML Parser. (Raise an issue to submit yours) | ||
To use it in **NPM package** install it first | ||
### Installation | ||
`$npm install fast-xml-parser` or using [yarn](https://yarnpkg.com/) `$yarn add fast-xml-parser` | ||
To use it as an **NPM package**: | ||
`npm install fast-xml-parser` | ||
Or using [yarn](https://yarnpkg.com/): | ||
`yarn add fast-xml-parser` | ||
To use it from a **CLI** install it globally with the `-g` option. | ||
`$npm install fast-xml-parser -g` | ||
`npm install fast-xml-parser -g` | ||
@@ -122,10 +130,10 @@ To use it on a **webpage** include it from a [CDN](https://cdnjs.com/libraries/fast-xml-parser) | ||
```js | ||
var jsonObj = parser.parse(xmlData [,options] ); | ||
const jsonObj = parser.parse(xmlData [,options] ); | ||
``` | ||
```js | ||
var parser = require('fast-xml-parser'); | ||
var he = require('he'); | ||
const parser = require('fast-xml-parser'); | ||
const he = require('he'); | ||
var options = { | ||
const options = { | ||
attributeNamePrefix : "@_", | ||
@@ -147,16 +155,17 @@ attrNodeName: "attr", //default is 'false' | ||
//skipLike: /\+[0-9]{10}/ | ||
} | ||
}, | ||
arrayMode: false, //"strict" | ||
attrValueProcessor: (val, attrName) => he.decode(val, {isAttributeValue: true}),//default is a=>a | ||
tagValueProcessor : (val, tagName) => he.decode(val), //default is a=>a | ||
stopNodes: ["parse-me-as-string"] | ||
stopNodes: ["parse-me-as-string"], | ||
alwaysCreateTextNode: false | ||
}; | ||
if( parser.validate(xmlData) === true) { //optional (it'll return an object in case it's not valid) | ||
var jsonObj = parser.parse(xmlData,options); | ||
let jsonObj = parser.parse(xmlData,options); | ||
} | ||
// Intermediate obj | ||
var tObj = parser.getTraversalObj(xmlData,options); | ||
var jsonObj = parser.convertToJson(tObj,options); | ||
const tObj = parser.getTraversalObj(xmlData,options); | ||
let jsonObj = parser.convertToJson(tObj,options); | ||
@@ -168,3 +177,3 @@ ``` | ||
try{ | ||
var jsonObj = parser.parse(xmlData,options, true); | ||
let jsonObj = parser.parse(xmlData,options, true); | ||
}catch(error){ | ||
@@ -208,3 +217,3 @@ console.log(error.message) | ||
* **stopNodes** : an array of tag names which are not required to be parsed. Instead their values are parsed as string. | ||
* **alwaysCreateTextNode** : When `true`, forces the parser always return a property for the `textNodeName` even if there are no attributes or node children. | ||
</details> | ||
@@ -232,5 +241,5 @@ | ||
```js | ||
var result = parser.validate(xmlData); | ||
const result = parser.validate(xmlData); | ||
if (result !== true) console.log(result.err); | ||
var jsonObj = parser.parse(xmlData); | ||
const jsonObj = parser.parse(xmlData); | ||
``` | ||
@@ -242,5 +251,5 @@ </details> | ||
```js | ||
var Parser = require("fast-xml-parser").j2xParser; | ||
const Parser = require("fast-xml-parser").j2xParser; | ||
//default options need not to set | ||
var defaultOptions = { | ||
const defaultOptions = { | ||
attributeNamePrefix : "@_", | ||
@@ -256,6 +265,7 @@ attrNodeName: "@", //default is false | ||
tagValueProcessor: a=> he.encode(a, { useNamedReferences: true}),// default is a=>a | ||
attrValueProcessor: a=> he.encode(a, {isAttributeValue: isAttribute, useNamedReferences: true})// default is a=>a | ||
attrValueProcessor: a=> he.encode(a, {isAttributeValue: isAttribute, useNamedReferences: true}),// default is a=>a | ||
rootNodeName: "element" | ||
}; | ||
var parser = new Parser(defaultOptions); | ||
var xml = parser.parse(json_or_js_obj); | ||
const parser = new Parser(defaultOptions); | ||
const xml = parser.parse(json_or_js_obj); | ||
``` | ||
@@ -279,2 +289,3 @@ | ||
* **attrValueProcessor** : Process attribute value during transformation. Like HTML encoding, word capitalization, etc. Applicable in case of string only. | ||
* **rootNodeName** : When input js object is array, parser uses array index by default as tag name. You can set this property for proper response. | ||
</details> | ||
@@ -281,0 +292,0 @@ |
@@ -35,2 +35,3 @@ 'use strict'; | ||
'attrValueProcessor', | ||
'rootNodeName', //when array as root | ||
]; | ||
@@ -83,2 +84,7 @@ | ||
Parser.prototype.parse = function(jObj) { | ||
if(Array.isArray(jObj) && this.options.rootNodeName && this.options.rootNodeName.length > 1){ | ||
jObj = { | ||
[this.options.rootNodeName] : jObj | ||
} | ||
} | ||
return this.j2x(jObj, 0).val; | ||
@@ -85,0 +91,0 @@ }; |
@@ -51,3 +51,3 @@ 'use strict'; | ||
const itemSchema = e_schema[0]; | ||
//var itemSchemaType = itemSchema; | ||
//const itemSchemaType = itemSchema; | ||
const arr_len = node.length; | ||
@@ -54,0 +54,0 @@ |
@@ -22,6 +22,6 @@ 'use strict'; | ||
for (let index = 0; index < keys.length; index++) { | ||
var tagname = keys[index]; | ||
const tagname = keys[index]; | ||
if (node.child[tagname] && node.child[tagname].length > 1) { | ||
jObj += '"' + tagname + '" : [ '; | ||
for (var tag in node.child[tagname]) { | ||
for (let tag in node.child[tagname]) { | ||
jObj += _cToJsonStr(node.child[tagname][tag], options) + ' , '; | ||
@@ -28,0 +28,0 @@ } |
@@ -9,3 +9,3 @@ 'use strict'; | ||
// when no child node or attr is present | ||
if ((!node.child || util.isEmptyObject(node.child)) && (!node.attrsMap || util.isEmptyObject(node.attrsMap))) { | ||
if (!options.alwaysCreateTextNode && (!node.child || util.isEmptyObject(node.child)) && (!node.attrsMap || util.isEmptyObject(node.attrsMap))) { | ||
return util.isExist(node.val) ? node.val : ''; | ||
@@ -12,0 +12,0 @@ } |
@@ -19,2 +19,3 @@ type X2jOptions = { | ||
stopNodes: string[]; | ||
alwaysCreateTextNode: boolean; | ||
}; | ||
@@ -49,3 +50,3 @@ type strnumOptions = { | ||
type ValidationError = { | ||
err: { code: string; msg: string, line: number }; | ||
err: { code: string; msg: string, line: number, col: number }; | ||
}; | ||
@@ -52,0 +53,0 @@ |
@@ -13,2 +13,3 @@ 'use strict'; | ||
const allmatches = []; | ||
allmatches.startIndex = regex.lastIndex - match[0].length; | ||
const len = match.length; | ||
@@ -71,3 +72,3 @@ for (let index = 0; index < len; index++) { | ||
exports.buildOptions = function(options, defaultOptions, props) { | ||
var newOptions = {}; | ||
let newOptions = {}; | ||
if (!options) { | ||
@@ -74,0 +75,0 @@ return defaultOptions; //if there are not options |
@@ -38,3 +38,3 @@ 'use strict'; | ||
//read until you reach to '>' avoiding any '>' in attribute value | ||
let tagStartPos = i; | ||
i++; | ||
@@ -75,3 +75,3 @@ | ||
if (tagName.trim().length === 0) { | ||
msg = "There is an unnecessary space between tag name and backward slash '</ ..'."; | ||
msg = "Invalid space after '<'."; | ||
} else { | ||
@@ -92,2 +92,3 @@ msg = "Tag '"+tagName+"' is an invalid name."; | ||
//self closing tag | ||
const attrStrStart = i - attrStr.length; | ||
attrStr = attrStr.substring(0, attrStr.length - 1); | ||
@@ -102,3 +103,3 @@ const isValid = validateAttributeString(attrStr, options); | ||
//this gives us the absolute index in the entire xml, which we can use to find the line at last | ||
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line)); | ||
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line)); | ||
} | ||
@@ -109,7 +110,10 @@ } else if (closingTag) { | ||
} else if (attrStr.trim().length > 0) { | ||
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, i)); | ||
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos)); | ||
} else { | ||
const otg = tags.pop(); | ||
if (tagName !== otg) { | ||
return getErrorObject('InvalidTag', "Closing tag '"+otg+"' is expected inplace of '"+tagName+"'.", getLineNumberForPosition(xmlData, i)); | ||
if (tagName !== otg.tagName) { | ||
let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos); | ||
return getErrorObject('InvalidTag', | ||
"Expected closing tag '"+otg.tagName+"' (opened in line "+openPos.line+", col "+openPos.col+") instead of closing tag '"+tagName+"'.", | ||
getLineNumberForPosition(xmlData, tagStartPos)); | ||
} | ||
@@ -135,3 +139,3 @@ | ||
} else { | ||
tags.push(tagName); | ||
tags.push({tagName, tagStartPos}); | ||
} | ||
@@ -177,4 +181,8 @@ tagFound = true; | ||
return getErrorObject('InvalidXml', 'Start tag expected.', 1); | ||
} else if (tags.length > 0) { | ||
return getErrorObject('InvalidXml', "Invalid '"+JSON.stringify(tags, null, 4).replace(/\r?\n/g, '')+"' found.", 1); | ||
}else if (tags.length == 1) { | ||
return getErrorObject('InvalidTag', "Unclosed tag '"+tags[0].tagName+"'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos)); | ||
}else if (tags.length > 0) { | ||
return getErrorObject('InvalidXml', "Invalid '"+ | ||
JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\r?\n/g, '')+ | ||
"' found.", {line: 1, col: 1}); | ||
} | ||
@@ -191,7 +199,7 @@ | ||
function readPI(xmlData, i) { | ||
var start = i; | ||
const start = i; | ||
for (; i < xmlData.length; i++) { | ||
if (xmlData[i] == '?' || xmlData[i] == ' ') { | ||
//tagname | ||
var tagname = xmlData.substr(start, i - start); | ||
const tagname = xmlData.substr(start, i - start); | ||
if (i > 5 && tagname === 'xml') { | ||
@@ -262,4 +270,4 @@ return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i)); | ||
var doubleQuote = '"'; | ||
var singleQuote = "'"; | ||
const doubleQuote = '"'; | ||
const singleQuote = "'"; | ||
@@ -281,3 +289,2 @@ /** | ||
//if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa | ||
continue; | ||
} else { | ||
@@ -323,6 +330,6 @@ startChar = ''; | ||
//nospace before attribute name: a="sd"b="saf" | ||
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(attrStr, matches[i][0])) | ||
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(matches[i])) | ||
} else if (matches[i][3] === undefined && !options.allowBooleanAttributes) { | ||
//independent attribute: ab | ||
return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(attrStr, matches[i][0])); | ||
return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(matches[i])); | ||
} | ||
@@ -334,3 +341,3 @@ /* else if(matches[i][6] === undefined){//attribute without value: ab= | ||
if (!validateAttrName(attrName)) { | ||
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(attrStr, matches[i][0])); | ||
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(matches[i])); | ||
} | ||
@@ -341,3 +348,3 @@ if (!attrNames.hasOwnProperty(attrName)) { | ||
} else { | ||
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(attrStr, matches[i][0])); | ||
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(matches[i])); | ||
} | ||
@@ -389,3 +396,4 @@ } | ||
msg: message, | ||
line: lineNumber, | ||
line: lineNumber.line || lineNumber, | ||
col: lineNumber.col, | ||
}, | ||
@@ -407,9 +415,14 @@ }; | ||
function getLineNumberForPosition(xmlData, index) { | ||
var lines = xmlData.substring(0, index).split(/\r?\n/); | ||
return lines.length; | ||
const lines = xmlData.substring(0, index).split(/\r?\n/); | ||
return { | ||
line: lines.length, | ||
// column number is last line's length + 1, because column numbering starts at 1: | ||
col: lines[lines.length - 1].length + 1 | ||
}; | ||
} | ||
//this function returns the position of the last character of match within attrStr | ||
function getPositionFromMatch(attrStr, match) { | ||
return attrStr.indexOf(match) + match.length; | ||
//this function returns the position of the first character of match within attrStr | ||
function getPositionFromMatch(match) { | ||
return match.startIndex + match[1].length; | ||
} |
@@ -47,3 +47,4 @@ 'use strict'; | ||
}, | ||
stopNodes: [] | ||
stopNodes: [], | ||
alwaysCreateTextNode: false | ||
//decodeStrict: false, | ||
@@ -71,3 +72,4 @@ }; | ||
'numParseOptions', | ||
'stopNodes' | ||
'stopNodes', | ||
'alwaysCreateTextNode' | ||
]; | ||
@@ -74,0 +76,0 @@ exports.props = props; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79514
13
1575
368
2
+ Addednyc@^15.1.0
+ Added@ampproject/remapping@2.3.0(transitive)
+ Added@babel/code-frame@7.25.7(transitive)
+ Added@babel/compat-data@7.25.7(transitive)
+ Added@babel/core@7.25.7(transitive)
+ Added@babel/generator@7.25.7(transitive)
+ Added@babel/helper-compilation-targets@7.25.7(transitive)
+ Added@babel/helper-module-imports@7.25.7(transitive)
+ Added@babel/helper-module-transforms@7.25.7(transitive)
+ Added@babel/helper-simple-access@7.25.7(transitive)
+ Added@babel/helper-string-parser@7.25.7(transitive)
+ Added@babel/helper-validator-identifier@7.25.7(transitive)
+ Added@babel/helper-validator-option@7.25.7(transitive)
+ Added@babel/helpers@7.25.7(transitive)
+ Added@babel/highlight@7.25.7(transitive)
+ Added@babel/parser@7.25.7(transitive)
+ Added@babel/template@7.25.7(transitive)
+ Added@babel/traverse@7.25.7(transitive)
+ Added@babel/types@7.25.7(transitive)
+ Added@istanbuljs/load-nyc-config@1.1.0(transitive)
+ Added@istanbuljs/schema@0.1.3(transitive)
+ Added@jridgewell/gen-mapping@0.3.5(transitive)
+ Added@jridgewell/resolve-uri@3.1.2(transitive)
+ Added@jridgewell/set-array@1.2.1(transitive)
+ Added@jridgewell/sourcemap-codec@1.5.0(transitive)
+ Added@jridgewell/trace-mapping@0.3.25(transitive)
+ Addedaggregate-error@3.1.0(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@3.2.14.3.0(transitive)
+ Addedappend-transform@2.0.0(transitive)
+ Addedarchy@1.0.0(transitive)
+ Addedargparse@1.0.10(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedbrowserslist@4.24.0(transitive)
+ Addedcaching-transform@4.0.0(transitive)
+ Addedcamelcase@5.3.1(transitive)
+ Addedcaniuse-lite@1.0.30001667(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedclean-stack@2.2.0(transitive)
+ Addedcliui@6.0.0(transitive)
+ Addedcolor-convert@1.9.32.0.1(transitive)
+ Addedcolor-name@1.1.31.1.4(transitive)
+ Addedcommondir@1.0.1(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedconvert-source-map@1.9.02.0.0(transitive)
+ Addedcross-spawn@7.0.3(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addeddecamelize@1.2.0(transitive)
+ Addeddefault-require-extensions@3.0.1(transitive)
+ Addedelectron-to-chromium@1.5.32(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedes6-error@4.1.1(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedfind-cache-dir@3.3.2(transitive)
+ Addedfind-up@4.1.0(transitive)
+ Addedforeground-child@2.0.0(transitive)
+ Addedfromentries@1.3.2(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedgensync@1.0.0-beta.2(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedget-package-type@0.1.0(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedglobals@11.12.0(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhas-flag@3.0.04.0.0(transitive)
+ Addedhasha@5.2.2(transitive)
+ Addedhtml-escaper@2.0.2(transitive)
+ Addedimurmurhash@0.1.4(transitive)
+ Addedindent-string@4.0.0(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedis-stream@2.0.1(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedis-windows@1.0.2(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedistanbul-lib-coverage@3.2.2(transitive)
+ Addedistanbul-lib-hook@3.0.0(transitive)
+ Addedistanbul-lib-instrument@4.0.3(transitive)
+ Addedistanbul-lib-processinfo@2.0.3(transitive)
+ Addedistanbul-lib-report@3.0.1(transitive)
+ Addedistanbul-lib-source-maps@4.0.1(transitive)
+ Addedistanbul-reports@3.1.7(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedjsesc@3.0.2(transitive)
+ Addedjson5@2.2.3(transitive)
+ Addedlocate-path@5.0.0(transitive)
+ Addedlodash.flattendeep@4.4.0(transitive)
+ Addedlru-cache@5.1.1(transitive)
+ Addedmake-dir@3.1.04.0.0(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedms@2.1.3(transitive)
+ Addednode-preload@0.2.1(transitive)
+ Addednode-releases@2.0.18(transitive)
+ Addednyc@15.1.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedp-limit@2.3.0(transitive)
+ Addedp-locate@4.1.0(transitive)
+ Addedp-map@3.0.0(transitive)
+ Addedp-try@2.2.0(transitive)
+ Addedpackage-hash@4.0.0(transitive)
+ Addedpath-exists@4.0.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedpicocolors@1.1.0(transitive)
+ Addedpkg-dir@4.2.0(transitive)
+ Addedprocess-on-spawn@1.0.0(transitive)
+ Addedrelease-zalgo@1.0.0(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedrequire-main-filename@2.0.0(transitive)
+ Addedresolve-from@5.0.0(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedsemver@6.3.17.6.3(transitive)
+ Addedset-blocking@2.0.0(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedspawn-wrap@2.0.0(transitive)
+ Addedsprintf-js@1.0.3(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedstrip-bom@4.0.0(transitive)
+ Addedsupports-color@5.5.07.2.0(transitive)
+ Addedtest-exclude@6.0.0(transitive)
+ Addedto-fast-properties@2.0.0(transitive)
+ Addedtype-fest@0.8.1(transitive)
+ Addedtypedarray-to-buffer@3.1.5(transitive)
+ Addedupdate-browserslist-db@1.1.1(transitive)
+ Addeduuid@8.3.2(transitive)
+ Addedwhich@2.0.2(transitive)
+ Addedwhich-module@2.0.1(transitive)
+ Addedwrap-ansi@6.2.0(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedwrite-file-atomic@3.0.3(transitive)
+ Addedy18n@4.0.3(transitive)
+ Addedyallist@3.1.1(transitive)
+ Addedyargs@15.4.1(transitive)
+ Addedyargs-parser@18.1.3(transitive)