├── .gitignore ├── CONTRIBUTING.md ├── Cakefile ├── LICENSE ├── README.md ├── lib ├── bom.js ├── builder.js ├── defaults.js ├── parser.js ├── processors.js └── xml2js.js ├── package-lock.json ├── package.json ├── src ├── bom.coffee ├── builder.coffee ├── defaults.coffee ├── parser.coffee ├── processors.coffee └── xml2js.coffee └── test ├── bom.test.coffee ├── builder.test.coffee ├── fixtures ├── build_sample.xml └── sample.xml ├── parser.test.coffee └── processors.test.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | node_modules 3 | npm-debug.log 4 | .nyc_output 5 | coverage 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We're always happy about useful new pull requests. Keep in mind that the better 4 | your pull request is, the easier it can be added to `xml2js`. As such please 5 | make sure your patch is ok: 6 | 7 | * `xml2js` is written in CoffeeScript. Please don't send patches to 8 | the JavaScript source, as it get's overwritten by the CoffeeScript 9 | compiler. The reason we have the JS code in the repository is for easier 10 | use with eg. `git submodule` 11 | * Make sure that the unit tests still all pass. Failing unit tests mean that 12 | someone *will* run into a bug, if we accept your pull request. 13 | * Please, add a unit test with your pull request, to show what was broken and 14 | is now fixed or what was impossible and now works due to your new code. 15 | * If you add a new feature, please add some documentation that it exists. 16 | 17 | If you like, you can add yourself in the `package.json` as contributor if you 18 | deem your contribution significant enough. Otherwise, we will decide and maybe 19 | add you. 20 | -------------------------------------------------------------------------------- /Cakefile: -------------------------------------------------------------------------------- 1 | {spawn, exec} = require 'child_process' 2 | 3 | task 'build', 'continually build the JavaScript code', -> 4 | coffeeScript = if process.platform == 'win32' then 'coffee.cmd' else 'coffee' 5 | coffee = spawn coffeeScript, ['-cw', '-o', 'lib', 'src'] 6 | coffee.stdout.on 'data', (data) -> console.log data.toString().trim() 7 | 8 | task 'doc', 'rebuild the Docco documentation', -> 9 | exec([ 10 | 'docco src/xml2js.coffee' 11 | ].join(' && '), (err) -> 12 | throw err if err 13 | ) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2011, 2012, 2013. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to 5 | deal in the Software without restriction, including without limitation the 6 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 | sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 | IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-xml2js 2 | =========== 3 | 4 | Ever had the urge to parse XML? And wanted to access the data in some sane, 5 | easy way? Don't want to compile a C parser, for whatever reason? Then xml2js is 6 | what you're looking for! 7 | 8 | Description 9 | =========== 10 | 11 | Simple XML to JavaScript object converter. It supports bi-directional conversion. 12 | Uses [sax-js](https://github.com/isaacs/sax-js/) and 13 | [xmlbuilder-js](https://github.com/oozcitak/xmlbuilder-js/). 14 | 15 | Note: If you're looking for a full DOM parser, you probably want 16 | [JSDom](https://github.com/tmpvar/jsdom). 17 | 18 | Installation 19 | ============ 20 | 21 | Simplest way to install `xml2js` is to use [npm](http://npmjs.org), just `npm 22 | install xml2js` which will download xml2js and all dependencies. 23 | 24 | xml2js is also available via [Bower](http://bower.io/), just `bower install 25 | xml2js` which will download xml2js and all dependencies. 26 | 27 | Usage 28 | ===== 29 | 30 | No extensive tutorials required because you are a smart developer! The task of 31 | parsing XML should be an easy one, so let's make it so! Here's some examples. 32 | 33 | Shoot-and-forget usage 34 | ---------------------- 35 | 36 | You want to parse XML as simple and easy as possible? It's dangerous to go 37 | alone, take this: 38 | 39 | ```javascript 40 | var parseString = require('xml2js').parseString; 41 | var xml = "Hello xml2js!" 42 | parseString(xml, function (err, result) { 43 | console.dir(result); 44 | }); 45 | ``` 46 | 47 | Can't get easier than this, right? This works starting with `xml2js` 0.2.3. 48 | With CoffeeScript it looks like this: 49 | 50 | ```coffeescript 51 | {parseString} = require 'xml2js' 52 | xml = "Hello xml2js!" 53 | parseString xml, (err, result) -> 54 | console.dir result 55 | ``` 56 | 57 | If you need some special options, fear not, `xml2js` supports a number of 58 | options (see below), you can specify these as second argument: 59 | 60 | ```javascript 61 | parseString(xml, {trim: true}, function (err, result) { 62 | }); 63 | ``` 64 | 65 | Simple as pie usage 66 | ------------------- 67 | 68 | That's right, if you have been using xml-simple or a home-grown 69 | wrapper, this was added in 0.1.11 just for you: 70 | 71 | ```javascript 72 | var fs = require('fs'), 73 | xml2js = require('xml2js'); 74 | 75 | var parser = new xml2js.Parser(); 76 | fs.readFile(__dirname + '/foo.xml', function(err, data) { 77 | parser.parseString(data, function (err, result) { 78 | console.dir(result); 79 | console.log('Done'); 80 | }); 81 | }); 82 | ``` 83 | 84 | Look ma, no event listeners! 85 | 86 | You can also use `xml2js` from 87 | [CoffeeScript](https://github.com/jashkenas/coffeescript), further reducing 88 | the clutter: 89 | 90 | ```coffeescript 91 | fs = require 'fs', 92 | xml2js = require 'xml2js' 93 | 94 | parser = new xml2js.Parser() 95 | fs.readFile __dirname + '/foo.xml', (err, data) -> 96 | parser.parseString data, (err, result) -> 97 | console.dir result 98 | console.log 'Done.' 99 | ``` 100 | 101 | But what happens if you forget the `new` keyword to create a new `Parser`? In 102 | the middle of a nightly coding session, it might get lost, after all. Worry 103 | not, we got you covered! Starting with 0.2.8 you can also leave it out, in 104 | which case `xml2js` will helpfully add it for you, no bad surprises and 105 | inexplicable bugs! 106 | 107 | Promise usage 108 | ------------- 109 | 110 | ```javascript 111 | var xml2js = require('xml2js'); 112 | var xml = ''; 113 | 114 | // With parser 115 | var parser = new xml2js.Parser(/* options */); 116 | parser.parseStringPromise(xml).then(function (result) { 117 | console.dir(result); 118 | console.log('Done'); 119 | }) 120 | .catch(function (err) { 121 | // Failed 122 | }); 123 | 124 | // Without parser 125 | xml2js.parseStringPromise(xml /*, options */).then(function (result) { 126 | console.dir(result); 127 | console.log('Done'); 128 | }) 129 | .catch(function (err) { 130 | // Failed 131 | }); 132 | ``` 133 | 134 | Parsing multiple files 135 | ---------------------- 136 | 137 | If you want to parse multiple files, you have multiple possibilities: 138 | 139 | * You can create one `xml2js.Parser` per file. That's the recommended one 140 | and is promised to always *just work*. 141 | * You can call `reset()` on your parser object. 142 | * You can hope everything goes well anyway. This behaviour is not 143 | guaranteed work always, if ever. Use option #1 if possible. Thanks! 144 | 145 | So you wanna some JSON? 146 | ----------------------- 147 | 148 | Just wrap the `result` object in a call to `JSON.stringify` like this 149 | `JSON.stringify(result)`. You get a string containing the JSON representation 150 | of the parsed object that you can feed to JSON-hungry consumers. 151 | 152 | Displaying results 153 | ------------------ 154 | 155 | You might wonder why, using `console.dir` or `console.log` the output at some 156 | level is only `[Object]`. Don't worry, this is not because `xml2js` got lazy. 157 | That's because Node uses `util.inspect` to convert the object into strings and 158 | that function stops after `depth=2` which is a bit low for most XML. 159 | 160 | To display the whole deal, you can use `console.log(util.inspect(result, false, 161 | null))`, which displays the whole result. 162 | 163 | So much for that, but what if you use 164 | [eyes](https://github.com/cloudhead/eyes.js) for nice colored output and it 165 | truncates the output with `…`? Don't fear, there's also a solution for that, 166 | you just need to increase the `maxLength` limit by creating a custom inspector 167 | `var inspect = require('eyes').inspector({maxLength: false})` and then you can 168 | easily `inspect(result)`. 169 | 170 | XML builder usage 171 | ----------------- 172 | 173 | Since 0.4.0, objects can be also be used to build XML: 174 | 175 | ```javascript 176 | var xml2js = require('xml2js'); 177 | 178 | var obj = {name: "Super", Surname: "Man", age: 23}; 179 | 180 | var builder = new xml2js.Builder(); 181 | var xml = builder.buildObject(obj); 182 | ``` 183 | will result in: 184 | 185 | ```xml 186 | 187 | 188 | Super 189 | Man 190 | 23 191 | 192 | ``` 193 | 194 | At the moment, a one to one bi-directional conversion is guaranteed only for 195 | default configuration, except for `attrkey`, `charkey` and `explicitArray` options 196 | you can redefine to your taste. Writing CDATA is supported via setting the `cdata` 197 | option to `true`. 198 | 199 | To specify attributes: 200 | ```javascript 201 | var xml2js = require('xml2js'); 202 | 203 | var obj = {root: {$: {id: "my id"}, _: "my inner text"}}; 204 | 205 | var builder = new xml2js.Builder(); 206 | var xml = builder.buildObject(obj); 207 | ``` 208 | will result in: 209 | ```xml 210 | 211 | my inner text 212 | ``` 213 | 214 | ### Adding xmlns attributes 215 | 216 | You can generate XML that declares XML namespace prefix / URI pairs with xmlns attributes. 217 | 218 | Example declaring a default namespace on the root element: 219 | 220 | ```javascript 221 | let obj = { 222 | Foo: { 223 | $: { 224 | "xmlns": "http://foo.com" 225 | } 226 | } 227 | }; 228 | ``` 229 | Result of `buildObject(obj)`: 230 | ```xml 231 | 232 | ``` 233 | Example declaring non-default namespaces on non-root elements: 234 | ```javascript 235 | let obj = { 236 | 'foo:Foo': { 237 | $: { 238 | 'xmlns:foo': 'http://foo.com' 239 | }, 240 | 'bar:Bar': { 241 | $: { 242 | 'xmlns:bar': 'http://bar.com' 243 | } 244 | } 245 | } 246 | } 247 | ``` 248 | Result of `buildObject(obj)`: 249 | ```xml 250 | 251 | 252 | 253 | ``` 254 | 255 | 256 | Processing attribute, tag names and values 257 | ------------------------------------------ 258 | 259 | Since 0.4.1 you can optionally provide the parser with attribute name and tag name processors as well as element value processors (Since 0.4.14, you can also optionally provide the parser with attribute value processors): 260 | 261 | ```javascript 262 | 263 | function nameToUpperCase(name){ 264 | return name.toUpperCase(); 265 | } 266 | 267 | //transform all attribute and tag names and values to uppercase 268 | parseString(xml, { 269 | tagNameProcessors: [nameToUpperCase], 270 | attrNameProcessors: [nameToUpperCase], 271 | valueProcessors: [nameToUpperCase], 272 | attrValueProcessors: [nameToUpperCase]}, 273 | function (err, result) { 274 | // processed data 275 | }); 276 | ``` 277 | 278 | The `tagNameProcessors` and `attrNameProcessors` options 279 | accept an `Array` of functions with the following signature: 280 | 281 | ```javascript 282 | function (name){ 283 | //do something with `name` 284 | return name 285 | } 286 | ``` 287 | 288 | The `attrValueProcessors` and `valueProcessors` options 289 | accept an `Array` of functions with the following signature: 290 | 291 | ```javascript 292 | function (value, name) { 293 | //`name` will be the node name or attribute name 294 | //do something with `value`, (optionally) dependent on the node/attr name 295 | return value 296 | } 297 | ``` 298 | 299 | Some processors are provided out-of-the-box and can be found in `lib/processors.js`: 300 | 301 | - `normalize`: transforms the name to lowercase. 302 | (Automatically used when `options.normalize` is set to `true`) 303 | 304 | - `firstCharLowerCase`: transforms the first character to lower case. 305 | E.g. 'MyTagName' becomes 'myTagName' 306 | 307 | - `stripPrefix`: strips the xml namespace prefix. E.g `` will become 'Bar'. 308 | (N.B.: the `xmlns` prefix is NOT stripped.) 309 | 310 | - `parseNumbers`: parses integer-like strings as integers and float-like strings as floats 311 | E.g. "0" becomes 0 and "15.56" becomes 15.56 312 | 313 | - `parseBooleans`: parses boolean-like strings to booleans 314 | E.g. "true" becomes true and "False" becomes false 315 | 316 | Options 317 | ======= 318 | 319 | Apart from the default settings, there are a number of options that can be 320 | specified for the parser. Options are specified by ``new Parser({optionName: 321 | value})``. Possible options are: 322 | 323 | * `attrkey` (default: `$`): Prefix that is used to access the attributes. 324 | Version 0.1 default was `@`. 325 | * `charkey` (default: `_`): Prefix that is used to access the character 326 | content. Version 0.1 default was `#`. 327 | * `explicitCharkey` (default: `false`) Determines whether or not to use 328 | a `charkey` prefix for elements with no attributes. 329 | * `trim` (default: `false`): Trim the whitespace at the beginning and end of 330 | text nodes. 331 | * `normalizeTags` (default: `false`): Normalize all tag names to lowercase. 332 | * `normalize` (default: `false`): Trim whitespaces inside text nodes. 333 | * `explicitRoot` (default: `true`): Set this if you want to get the root 334 | node in the resulting object. 335 | * `emptyTag` (default: `''`): what will the value of empty nodes be. In case 336 | you want to use an empty object as a default value, it is better to provide a factory 337 | function `() => ({})` instead. Without this function a plain object would 338 | become a shared reference across all occurrences with unwanted behavior. 339 | * `explicitArray` (default: `true`): Always put child nodes in an array if 340 | true; otherwise an array is created only if there is more than one. 341 | * `ignoreAttrs` (default: `false`): Ignore all XML attributes and only create 342 | text nodes. 343 | * `mergeAttrs` (default: `false`): Merge attributes and child elements as 344 | properties of the parent, instead of keying attributes off a child 345 | attribute object. This option is ignored if `ignoreAttrs` is `true`. 346 | * `validator` (default `null`): You can specify a callable that validates 347 | the resulting structure somehow, however you want. See unit tests 348 | for an example. 349 | * `xmlns` (default `false`): Give each element a field usually called '$ns' 350 | (the first character is the same as attrkey) that contains its local name 351 | and namespace URI. 352 | * `explicitChildren` (default `false`): Put child elements to separate 353 | property. Doesn't work with `mergeAttrs = true`. If element has no children 354 | then "children" won't be created. Added in 0.2.5. 355 | * `childkey` (default `$$`): Prefix that is used to access child elements if 356 | `explicitChildren` is set to `true`. Added in 0.2.5. 357 | * `preserveChildrenOrder` (default `false`): Modifies the behavior of 358 | `explicitChildren` so that the value of the "children" property becomes an 359 | ordered array. When this is `true`, every node will also get a `#name` field 360 | whose value will correspond to the XML nodeName, so that you may iterate 361 | the "children" array and still be able to determine node names. The named 362 | (and potentially unordered) properties are also retained in this 363 | configuration at the same level as the ordered "children" array. Added in 364 | 0.4.9. 365 | * `charsAsChildren` (default `false`): Determines whether chars should be 366 | considered children if `explicitChildren` is on. Added in 0.2.5. 367 | * `includeWhiteChars` (default `false`): Determines whether whitespace-only 368 | text nodes should be included. Added in 0.4.17. 369 | * `async` (default `false`): Should the callbacks be async? This *might* be 370 | an incompatible change if your code depends on sync execution of callbacks. 371 | Future versions of `xml2js` might change this default, so the recommendation 372 | is to not depend on sync execution anyway. Added in 0.2.6. 373 | * `strict` (default `true`): Set sax-js to strict or non-strict parsing mode. 374 | Defaults to `true` which is *highly* recommended, since parsing HTML which 375 | is not well-formed XML might yield just about anything. Added in 0.2.7. 376 | * `attrNameProcessors` (default: `null`): Allows the addition of attribute 377 | name processing functions. Accepts an `Array` of functions with following 378 | signature: 379 | ```javascript 380 | function (name){ 381 | //do something with `name` 382 | return name 383 | } 384 | ``` 385 | Added in 0.4.14 386 | * `attrValueProcessors` (default: `null`): Allows the addition of attribute 387 | value processing functions. Accepts an `Array` of functions with following 388 | signature: 389 | ```javascript 390 | function (value, name){ 391 | //do something with `name` 392 | return name 393 | } 394 | ``` 395 | Added in 0.4.1 396 | * `tagNameProcessors` (default: `null`): Allows the addition of tag name 397 | processing functions. Accepts an `Array` of functions with following 398 | signature: 399 | ```javascript 400 | function (name){ 401 | //do something with `name` 402 | return name 403 | } 404 | ``` 405 | Added in 0.4.1 406 | * `valueProcessors` (default: `null`): Allows the addition of element value 407 | processing functions. Accepts an `Array` of functions with following 408 | signature: 409 | ```javascript 410 | function (value, name){ 411 | //do something with `name` 412 | return name 413 | } 414 | ``` 415 | Added in 0.4.6 416 | 417 | Options for the `Builder` class 418 | ------------------------------- 419 | These options are specified by ``new Builder({optionName: value})``. 420 | Possible options are: 421 | 422 | * `attrkey` (default: `$`): Prefix that is used to access the attributes. 423 | Version 0.1 default was `@`. 424 | * `charkey` (default: `_`): Prefix that is used to access the character 425 | content. Version 0.1 default was `#`. 426 | * `rootName` (default `root` or the root key name): root element name to be used in case 427 | `explicitRoot` is `false` or to override the root element name. 428 | * `renderOpts` (default `{ 'pretty': true, 'indent': ' ', 'newline': '\n' }`): 429 | Rendering options for xmlbuilder-js. 430 | * pretty: prettify generated XML 431 | * indent: whitespace for indentation (only when pretty) 432 | * newline: newline char (only when pretty) 433 | * `xmldec` (default `{ 'version': '1.0', 'encoding': 'UTF-8', 'standalone': true }`: 434 | XML declaration attributes. 435 | * `xmldec.version` A version number string, e.g. 1.0 436 | * `xmldec.encoding` Encoding declaration, e.g. UTF-8 437 | * `xmldec.standalone` standalone document declaration: true or false 438 | * `doctype` (default `null`): optional DTD. Eg. `{'ext': 'hello.dtd'}` 439 | * `headless` (default: `false`): omit the XML header. Added in 0.4.3. 440 | * `allowSurrogateChars` (default: `false`): allows using characters from the Unicode 441 | surrogate blocks. 442 | * `cdata` (default: `false`): wrap text nodes in `` instead of 443 | escaping when necessary. Does not add `` if it is not required. 444 | Added in 0.4.5. 445 | 446 | `renderOpts`, `xmldec`,`doctype` and `headless` pass through to 447 | [xmlbuilder-js](https://github.com/oozcitak/xmlbuilder-js). 448 | 449 | Updating to new version 450 | ======================= 451 | 452 | Version 0.2 changed the default parsing settings, but version 0.1.14 introduced 453 | the default settings for version 0.2, so these settings can be tried before the 454 | migration. 455 | 456 | ```javascript 457 | var xml2js = require('xml2js'); 458 | var parser = new xml2js.Parser(xml2js.defaults["0.2"]); 459 | ``` 460 | 461 | To get the 0.1 defaults in version 0.2 you can just use 462 | `xml2js.defaults["0.1"]` in the same place. This provides you with enough time 463 | to migrate to the saner way of parsing in `xml2js` 0.2. We try to make the 464 | migration as simple and gentle as possible, but some breakage cannot be 465 | avoided. 466 | 467 | So, what exactly did change and why? In 0.2 we changed some defaults to parse 468 | the XML in a more universal and sane way. So we disabled `normalize` and `trim` 469 | so `xml2js` does not cut out any text content. You can reenable this at will of 470 | course. A more important change is that we return the root tag in the resulting 471 | JavaScript structure via the `explicitRoot` setting, so you need to access the 472 | first element. This is useful for anybody who wants to know what the root node 473 | is and preserves more information. The last major change was to enable 474 | `explicitArray`, so everytime it is possible that one might embed more than one 475 | sub-tag into a tag, xml2js >= 0.2 returns an array even if the array just 476 | includes one element. This is useful when dealing with APIs that return 477 | variable amounts of subtags. 478 | 479 | Running tests, development 480 | ========================== 481 | 482 | [![Build Status](https://travis-ci.org/Leonidas-from-XIV/node-xml2js.svg?branch=master)](https://travis-ci.org/Leonidas-from-XIV/node-xml2js) 483 | [![Coverage Status](https://coveralls.io/repos/Leonidas-from-XIV/node-xml2js/badge.svg?branch=)](https://coveralls.io/r/Leonidas-from-XIV/node-xml2js?branch=master) 484 | [![Dependency Status](https://david-dm.org/Leonidas-from-XIV/node-xml2js.svg)](https://david-dm.org/Leonidas-from-XIV/node-xml2js) 485 | 486 | The development requirements are handled by npm, you just need to install them. 487 | We also have a number of unit tests, they can be run using `npm test` directly 488 | from the project root. This runs zap to discover all the tests and execute 489 | them. 490 | 491 | If you like to contribute, keep in mind that `xml2js` is written in 492 | CoffeeScript, so don't develop on the JavaScript files that are checked into 493 | the repository for convenience reasons. Also, please write some unit test to 494 | check your behaviour and if it is some user-facing thing, add some 495 | documentation to this README, so people will know it exists. Thanks in advance! 496 | 497 | Getting support 498 | =============== 499 | 500 | Please, if you have a problem with the library, first make sure you read this 501 | README. If you read this far, thanks, you're good. Then, please make sure your 502 | problem really is with `xml2js`. It is? Okay, then I'll look at it. Send me a 503 | mail and we can talk. Please don't open issues, as I don't think that is the 504 | proper forum for support problems. Some problems might as well really be bugs 505 | in `xml2js`, if so I'll let you know to open an issue instead :) 506 | 507 | But if you know you really found a bug, feel free to open an issue instead. 508 | -------------------------------------------------------------------------------- /lib/bom.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.12.7 2 | (function() { 3 | "use strict"; 4 | exports.stripBOM = function(str) { 5 | if (str[0] === '\uFEFF') { 6 | return str.substring(1); 7 | } else { 8 | return str; 9 | } 10 | }; 11 | 12 | }).call(this); 13 | -------------------------------------------------------------------------------- /lib/builder.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.12.7 2 | (function() { 3 | "use strict"; 4 | var builder, defaults, escapeCDATA, requiresCDATA, wrapCDATA, 5 | hasProp = {}.hasOwnProperty; 6 | 7 | builder = require('xmlbuilder'); 8 | 9 | defaults = require('./defaults').defaults; 10 | 11 | requiresCDATA = function(entry) { 12 | return typeof entry === "string" && (entry.indexOf('&') >= 0 || entry.indexOf('>') >= 0 || entry.indexOf('<') >= 0); 13 | }; 14 | 15 | wrapCDATA = function(entry) { 16 | return ""; 17 | }; 18 | 19 | escapeCDATA = function(entry) { 20 | return entry.replace(']]>', ']]]]>'); 21 | }; 22 | 23 | exports.Builder = (function() { 24 | function Builder(opts) { 25 | var key, ref, value; 26 | this.options = {}; 27 | ref = defaults["0.2"]; 28 | for (key in ref) { 29 | if (!hasProp.call(ref, key)) continue; 30 | value = ref[key]; 31 | this.options[key] = value; 32 | } 33 | for (key in opts) { 34 | if (!hasProp.call(opts, key)) continue; 35 | value = opts[key]; 36 | this.options[key] = value; 37 | } 38 | } 39 | 40 | Builder.prototype.buildObject = function(rootObj) { 41 | var attrkey, charkey, render, rootElement, rootName; 42 | attrkey = this.options.attrkey; 43 | charkey = this.options.charkey; 44 | if ((Object.keys(rootObj).length === 1) && (this.options.rootName === defaults['0.2'].rootName)) { 45 | rootName = Object.keys(rootObj)[0]; 46 | rootObj = rootObj[rootName]; 47 | } else { 48 | rootName = this.options.rootName; 49 | } 50 | render = (function(_this) { 51 | return function(element, obj) { 52 | var attr, child, entry, index, key, value; 53 | if (typeof obj !== 'object') { 54 | if (_this.options.cdata && requiresCDATA(obj)) { 55 | element.raw(wrapCDATA(obj)); 56 | } else { 57 | element.txt(obj); 58 | } 59 | } else if (Array.isArray(obj)) { 60 | for (index in obj) { 61 | if (!hasProp.call(obj, index)) continue; 62 | child = obj[index]; 63 | for (key in child) { 64 | entry = child[key]; 65 | element = render(element.ele(key), entry).up(); 66 | } 67 | } 68 | } else { 69 | for (key in obj) { 70 | if (!hasProp.call(obj, key)) continue; 71 | child = obj[key]; 72 | if (key === attrkey) { 73 | if (typeof child === "object") { 74 | for (attr in child) { 75 | value = child[attr]; 76 | element = element.att(attr, value); 77 | } 78 | } 79 | } else if (key === charkey) { 80 | if (_this.options.cdata && requiresCDATA(child)) { 81 | element = element.raw(wrapCDATA(child)); 82 | } else { 83 | element = element.txt(child); 84 | } 85 | } else if (Array.isArray(child)) { 86 | for (index in child) { 87 | if (!hasProp.call(child, index)) continue; 88 | entry = child[index]; 89 | if (typeof entry === 'string') { 90 | if (_this.options.cdata && requiresCDATA(entry)) { 91 | element = element.ele(key).raw(wrapCDATA(entry)).up(); 92 | } else { 93 | element = element.ele(key, entry).up(); 94 | } 95 | } else { 96 | element = render(element.ele(key), entry).up(); 97 | } 98 | } 99 | } else if (typeof child === "object") { 100 | element = render(element.ele(key), child).up(); 101 | } else { 102 | if (typeof child === 'string' && _this.options.cdata && requiresCDATA(child)) { 103 | element = element.ele(key).raw(wrapCDATA(child)).up(); 104 | } else { 105 | if (child == null) { 106 | child = ''; 107 | } 108 | element = element.ele(key, child.toString()).up(); 109 | } 110 | } 111 | } 112 | } 113 | return element; 114 | }; 115 | })(this); 116 | rootElement = builder.create(rootName, this.options.xmldec, this.options.doctype, { 117 | headless: this.options.headless, 118 | allowSurrogateChars: this.options.allowSurrogateChars 119 | }); 120 | return render(rootElement, rootObj).end(this.options.renderOpts); 121 | }; 122 | 123 | return Builder; 124 | 125 | })(); 126 | 127 | }).call(this); 128 | -------------------------------------------------------------------------------- /lib/defaults.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.12.7 2 | (function() { 3 | exports.defaults = { 4 | "0.1": { 5 | explicitCharkey: false, 6 | trim: true, 7 | normalize: true, 8 | normalizeTags: false, 9 | attrkey: "@", 10 | charkey: "#", 11 | explicitArray: false, 12 | ignoreAttrs: false, 13 | mergeAttrs: false, 14 | explicitRoot: false, 15 | validator: null, 16 | xmlns: false, 17 | explicitChildren: false, 18 | childkey: '@@', 19 | charsAsChildren: false, 20 | includeWhiteChars: false, 21 | async: false, 22 | strict: true, 23 | attrNameProcessors: null, 24 | attrValueProcessors: null, 25 | tagNameProcessors: null, 26 | valueProcessors: null, 27 | emptyTag: '' 28 | }, 29 | "0.2": { 30 | explicitCharkey: false, 31 | trim: false, 32 | normalize: false, 33 | normalizeTags: false, 34 | attrkey: "$", 35 | charkey: "_", 36 | explicitArray: true, 37 | ignoreAttrs: false, 38 | mergeAttrs: false, 39 | explicitRoot: true, 40 | validator: null, 41 | xmlns: false, 42 | explicitChildren: false, 43 | preserveChildrenOrder: false, 44 | childkey: '$$', 45 | charsAsChildren: false, 46 | includeWhiteChars: false, 47 | async: false, 48 | strict: true, 49 | attrNameProcessors: null, 50 | attrValueProcessors: null, 51 | tagNameProcessors: null, 52 | valueProcessors: null, 53 | rootName: 'root', 54 | xmldec: { 55 | 'version': '1.0', 56 | 'encoding': 'UTF-8', 57 | 'standalone': true 58 | }, 59 | doctype: null, 60 | renderOpts: { 61 | 'pretty': true, 62 | 'indent': ' ', 63 | 'newline': '\n' 64 | }, 65 | headless: false, 66 | chunkSize: 10000, 67 | emptyTag: '', 68 | cdata: false 69 | } 70 | }; 71 | 72 | }).call(this); 73 | -------------------------------------------------------------------------------- /lib/parser.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.12.7 2 | (function() { 3 | "use strict"; 4 | var bom, defaults, defineProperty, events, isEmpty, processItem, processors, sax, setImmediate, 5 | bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 6 | extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 7 | hasProp = {}.hasOwnProperty; 8 | 9 | sax = require('sax'); 10 | 11 | events = require('events'); 12 | 13 | bom = require('./bom'); 14 | 15 | processors = require('./processors'); 16 | 17 | setImmediate = require('timers').setImmediate; 18 | 19 | defaults = require('./defaults').defaults; 20 | 21 | isEmpty = function(thing) { 22 | return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0; 23 | }; 24 | 25 | processItem = function(processors, item, key) { 26 | var i, len, process; 27 | for (i = 0, len = processors.length; i < len; i++) { 28 | process = processors[i]; 29 | item = process(item, key); 30 | } 31 | return item; 32 | }; 33 | 34 | defineProperty = function(obj, key, value) { 35 | var descriptor; 36 | descriptor = Object.create(null); 37 | descriptor.value = value; 38 | descriptor.writable = true; 39 | descriptor.enumerable = true; 40 | descriptor.configurable = true; 41 | return Object.defineProperty(obj, key, descriptor); 42 | }; 43 | 44 | exports.Parser = (function(superClass) { 45 | extend(Parser, superClass); 46 | 47 | function Parser(opts) { 48 | this.parseStringPromise = bind(this.parseStringPromise, this); 49 | this.parseString = bind(this.parseString, this); 50 | this.reset = bind(this.reset, this); 51 | this.assignOrPush = bind(this.assignOrPush, this); 52 | this.processAsync = bind(this.processAsync, this); 53 | var key, ref, value; 54 | if (!(this instanceof exports.Parser)) { 55 | return new exports.Parser(opts); 56 | } 57 | this.options = {}; 58 | ref = defaults["0.2"]; 59 | for (key in ref) { 60 | if (!hasProp.call(ref, key)) continue; 61 | value = ref[key]; 62 | this.options[key] = value; 63 | } 64 | for (key in opts) { 65 | if (!hasProp.call(opts, key)) continue; 66 | value = opts[key]; 67 | this.options[key] = value; 68 | } 69 | if (this.options.xmlns) { 70 | this.options.xmlnskey = this.options.attrkey + "ns"; 71 | } 72 | if (this.options.normalizeTags) { 73 | if (!this.options.tagNameProcessors) { 74 | this.options.tagNameProcessors = []; 75 | } 76 | this.options.tagNameProcessors.unshift(processors.normalize); 77 | } 78 | this.reset(); 79 | } 80 | 81 | Parser.prototype.processAsync = function() { 82 | var chunk, err; 83 | try { 84 | if (this.remaining.length <= this.options.chunkSize) { 85 | chunk = this.remaining; 86 | this.remaining = ''; 87 | this.saxParser = this.saxParser.write(chunk); 88 | return this.saxParser.close(); 89 | } else { 90 | chunk = this.remaining.substr(0, this.options.chunkSize); 91 | this.remaining = this.remaining.substr(this.options.chunkSize, this.remaining.length); 92 | this.saxParser = this.saxParser.write(chunk); 93 | return setImmediate(this.processAsync); 94 | } 95 | } catch (error1) { 96 | err = error1; 97 | if (!this.saxParser.errThrown) { 98 | this.saxParser.errThrown = true; 99 | return this.emit(err); 100 | } 101 | } 102 | }; 103 | 104 | Parser.prototype.assignOrPush = function(obj, key, newValue) { 105 | if (!(key in obj)) { 106 | if (!this.options.explicitArray) { 107 | return defineProperty(obj, key, newValue); 108 | } else { 109 | return defineProperty(obj, key, [newValue]); 110 | } 111 | } else { 112 | if (!(obj[key] instanceof Array)) { 113 | defineProperty(obj, key, [obj[key]]); 114 | } 115 | return obj[key].push(newValue); 116 | } 117 | }; 118 | 119 | Parser.prototype.reset = function() { 120 | var attrkey, charkey, ontext, stack; 121 | this.removeAllListeners(); 122 | this.saxParser = sax.parser(this.options.strict, { 123 | trim: false, 124 | normalize: false, 125 | xmlns: this.options.xmlns 126 | }); 127 | this.saxParser.errThrown = false; 128 | this.saxParser.onerror = (function(_this) { 129 | return function(error) { 130 | _this.saxParser.resume(); 131 | if (!_this.saxParser.errThrown) { 132 | _this.saxParser.errThrown = true; 133 | return _this.emit("error", error); 134 | } 135 | }; 136 | })(this); 137 | this.saxParser.onend = (function(_this) { 138 | return function() { 139 | if (!_this.saxParser.ended) { 140 | _this.saxParser.ended = true; 141 | return _this.emit("end", _this.resultObject); 142 | } 143 | }; 144 | })(this); 145 | this.saxParser.ended = false; 146 | this.EXPLICIT_CHARKEY = this.options.explicitCharkey; 147 | this.resultObject = null; 148 | stack = []; 149 | attrkey = this.options.attrkey; 150 | charkey = this.options.charkey; 151 | this.saxParser.onopentag = (function(_this) { 152 | return function(node) { 153 | var key, newValue, obj, processedKey, ref; 154 | obj = {}; 155 | obj[charkey] = ""; 156 | if (!_this.options.ignoreAttrs) { 157 | ref = node.attributes; 158 | for (key in ref) { 159 | if (!hasProp.call(ref, key)) continue; 160 | if (!(attrkey in obj) && !_this.options.mergeAttrs) { 161 | obj[attrkey] = {}; 162 | } 163 | newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key]; 164 | processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key; 165 | if (_this.options.mergeAttrs) { 166 | _this.assignOrPush(obj, processedKey, newValue); 167 | } else { 168 | defineProperty(obj[attrkey], processedKey, newValue); 169 | } 170 | } 171 | } 172 | obj["#name"] = _this.options.tagNameProcessors ? processItem(_this.options.tagNameProcessors, node.name) : node.name; 173 | if (_this.options.xmlns) { 174 | obj[_this.options.xmlnskey] = { 175 | uri: node.uri, 176 | local: node.local 177 | }; 178 | } 179 | return stack.push(obj); 180 | }; 181 | })(this); 182 | this.saxParser.onclosetag = (function(_this) { 183 | return function() { 184 | var cdata, emptyStr, key, node, nodeName, obj, objClone, old, s, xpath; 185 | obj = stack.pop(); 186 | nodeName = obj["#name"]; 187 | if (!_this.options.explicitChildren || !_this.options.preserveChildrenOrder) { 188 | delete obj["#name"]; 189 | } 190 | if (obj.cdata === true) { 191 | cdata = obj.cdata; 192 | delete obj.cdata; 193 | } 194 | s = stack[stack.length - 1]; 195 | if (obj[charkey].match(/^\s*$/) && !cdata) { 196 | emptyStr = obj[charkey]; 197 | delete obj[charkey]; 198 | } else { 199 | if (_this.options.trim) { 200 | obj[charkey] = obj[charkey].trim(); 201 | } 202 | if (_this.options.normalize) { 203 | obj[charkey] = obj[charkey].replace(/\s{2,}/g, " ").trim(); 204 | } 205 | obj[charkey] = _this.options.valueProcessors ? processItem(_this.options.valueProcessors, obj[charkey], nodeName) : obj[charkey]; 206 | if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) { 207 | obj = obj[charkey]; 208 | } 209 | } 210 | if (isEmpty(obj)) { 211 | if (typeof _this.options.emptyTag === 'function') { 212 | obj = _this.options.emptyTag(); 213 | } else { 214 | obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr; 215 | } 216 | } 217 | if (_this.options.validator != null) { 218 | xpath = "/" + ((function() { 219 | var i, len, results; 220 | results = []; 221 | for (i = 0, len = stack.length; i < len; i++) { 222 | node = stack[i]; 223 | results.push(node["#name"]); 224 | } 225 | return results; 226 | })()).concat(nodeName).join("/"); 227 | (function() { 228 | var err; 229 | try { 230 | return obj = _this.options.validator(xpath, s && s[nodeName], obj); 231 | } catch (error1) { 232 | err = error1; 233 | return _this.emit("error", err); 234 | } 235 | })(); 236 | } 237 | if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') { 238 | if (!_this.options.preserveChildrenOrder) { 239 | node = {}; 240 | if (_this.options.attrkey in obj) { 241 | node[_this.options.attrkey] = obj[_this.options.attrkey]; 242 | delete obj[_this.options.attrkey]; 243 | } 244 | if (!_this.options.charsAsChildren && _this.options.charkey in obj) { 245 | node[_this.options.charkey] = obj[_this.options.charkey]; 246 | delete obj[_this.options.charkey]; 247 | } 248 | if (Object.getOwnPropertyNames(obj).length > 0) { 249 | node[_this.options.childkey] = obj; 250 | } 251 | obj = node; 252 | } else if (s) { 253 | s[_this.options.childkey] = s[_this.options.childkey] || []; 254 | objClone = {}; 255 | for (key in obj) { 256 | if (!hasProp.call(obj, key)) continue; 257 | defineProperty(objClone, key, obj[key]); 258 | } 259 | s[_this.options.childkey].push(objClone); 260 | delete obj["#name"]; 261 | if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) { 262 | obj = obj[charkey]; 263 | } 264 | } 265 | } 266 | if (stack.length > 0) { 267 | return _this.assignOrPush(s, nodeName, obj); 268 | } else { 269 | if (_this.options.explicitRoot) { 270 | old = obj; 271 | obj = {}; 272 | defineProperty(obj, nodeName, old); 273 | } 274 | _this.resultObject = obj; 275 | _this.saxParser.ended = true; 276 | return _this.emit("end", _this.resultObject); 277 | } 278 | }; 279 | })(this); 280 | ontext = (function(_this) { 281 | return function(text) { 282 | var charChild, s; 283 | s = stack[stack.length - 1]; 284 | if (s) { 285 | s[charkey] += text; 286 | if (_this.options.explicitChildren && _this.options.preserveChildrenOrder && _this.options.charsAsChildren && (_this.options.includeWhiteChars || text.replace(/\\n/g, '').trim() !== '')) { 287 | s[_this.options.childkey] = s[_this.options.childkey] || []; 288 | charChild = { 289 | '#name': '__text__' 290 | }; 291 | charChild[charkey] = text; 292 | if (_this.options.normalize) { 293 | charChild[charkey] = charChild[charkey].replace(/\s{2,}/g, " ").trim(); 294 | } 295 | s[_this.options.childkey].push(charChild); 296 | } 297 | return s; 298 | } 299 | }; 300 | })(this); 301 | this.saxParser.ontext = ontext; 302 | return this.saxParser.oncdata = (function(_this) { 303 | return function(text) { 304 | var s; 305 | s = ontext(text); 306 | if (s) { 307 | return s.cdata = true; 308 | } 309 | }; 310 | })(this); 311 | }; 312 | 313 | Parser.prototype.parseString = function(str, cb) { 314 | var err; 315 | if ((cb != null) && typeof cb === "function") { 316 | this.on("end", function(result) { 317 | this.reset(); 318 | return cb(null, result); 319 | }); 320 | this.on("error", function(err) { 321 | this.reset(); 322 | return cb(err); 323 | }); 324 | } 325 | try { 326 | str = str.toString(); 327 | if (str.trim() === '') { 328 | this.emit("end", null); 329 | return true; 330 | } 331 | str = bom.stripBOM(str); 332 | if (this.options.async) { 333 | this.remaining = str; 334 | setImmediate(this.processAsync); 335 | return this.saxParser; 336 | } 337 | return this.saxParser.write(str).close(); 338 | } catch (error1) { 339 | err = error1; 340 | if (!(this.saxParser.errThrown || this.saxParser.ended)) { 341 | this.emit('error', err); 342 | return this.saxParser.errThrown = true; 343 | } else if (this.saxParser.ended) { 344 | throw err; 345 | } 346 | } 347 | }; 348 | 349 | Parser.prototype.parseStringPromise = function(str) { 350 | return new Promise((function(_this) { 351 | return function(resolve, reject) { 352 | return _this.parseString(str, function(err, value) { 353 | if (err) { 354 | return reject(err); 355 | } else { 356 | return resolve(value); 357 | } 358 | }); 359 | }; 360 | })(this)); 361 | }; 362 | 363 | return Parser; 364 | 365 | })(events); 366 | 367 | exports.parseString = function(str, a, b) { 368 | var cb, options, parser; 369 | if (b != null) { 370 | if (typeof b === 'function') { 371 | cb = b; 372 | } 373 | if (typeof a === 'object') { 374 | options = a; 375 | } 376 | } else { 377 | if (typeof a === 'function') { 378 | cb = a; 379 | } 380 | options = {}; 381 | } 382 | parser = new exports.Parser(options); 383 | return parser.parseString(str, cb); 384 | }; 385 | 386 | exports.parseStringPromise = function(str, a) { 387 | var options, parser; 388 | if (typeof a === 'object') { 389 | options = a; 390 | } 391 | parser = new exports.Parser(options); 392 | return parser.parseStringPromise(str); 393 | }; 394 | 395 | }).call(this); 396 | -------------------------------------------------------------------------------- /lib/processors.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.12.7 2 | (function() { 3 | "use strict"; 4 | var prefixMatch; 5 | 6 | prefixMatch = new RegExp(/(?!xmlns)^.*:/); 7 | 8 | exports.normalize = function(str) { 9 | return str.toLowerCase(); 10 | }; 11 | 12 | exports.firstCharLowerCase = function(str) { 13 | return str.charAt(0).toLowerCase() + str.slice(1); 14 | }; 15 | 16 | exports.stripPrefix = function(str) { 17 | return str.replace(prefixMatch, ''); 18 | }; 19 | 20 | exports.parseNumbers = function(str) { 21 | if (!isNaN(str)) { 22 | str = str % 1 === 0 ? parseInt(str, 10) : parseFloat(str); 23 | } 24 | return str; 25 | }; 26 | 27 | exports.parseBooleans = function(str) { 28 | if (/^(?:true|false)$/i.test(str)) { 29 | str = str.toLowerCase() === 'true'; 30 | } 31 | return str; 32 | }; 33 | 34 | }).call(this); 35 | -------------------------------------------------------------------------------- /lib/xml2js.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.12.7 2 | (function() { 3 | "use strict"; 4 | var builder, defaults, parser, processors, 5 | extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 6 | hasProp = {}.hasOwnProperty; 7 | 8 | defaults = require('./defaults'); 9 | 10 | builder = require('./builder'); 11 | 12 | parser = require('./parser'); 13 | 14 | processors = require('./processors'); 15 | 16 | exports.defaults = defaults.defaults; 17 | 18 | exports.processors = processors; 19 | 20 | exports.ValidationError = (function(superClass) { 21 | extend(ValidationError, superClass); 22 | 23 | function ValidationError(message) { 24 | this.message = message; 25 | } 26 | 27 | return ValidationError; 28 | 29 | })(Error); 30 | 31 | exports.Builder = builder.Builder; 32 | 33 | exports.Parser = parser.Parser; 34 | 35 | exports.parseString = parser.parseString; 36 | 37 | exports.parseStringPromise = parser.parseStringPromise; 38 | 39 | }).call(this); 40 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xml2js", 3 | "version": "0.6.2", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "xml2js", 9 | "version": "0.6.2", 10 | "license": "MIT", 11 | "dependencies": { 12 | "sax": ">=0.6.0", 13 | "xmlbuilder": "~11.0.0" 14 | }, 15 | "devDependencies": { 16 | "coffeescript": ">=1.10.0 <2", 17 | "coveralls": "^3.0.1", 18 | "diff": ">=1.0.8", 19 | "docco": ">=0.6.2", 20 | "nyc": ">=2.2.1", 21 | "zap": ">=0.2.9 <1" 22 | }, 23 | "engines": { 24 | "node": ">=4.0.0" 25 | } 26 | }, 27 | "node_modules/@babel/code-frame": { 28 | "version": "7.5.5", 29 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", 30 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", 31 | "dev": true, 32 | "dependencies": { 33 | "@babel/highlight": "^7.0.0" 34 | } 35 | }, 36 | "node_modules/@babel/generator": { 37 | "version": "7.5.5", 38 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", 39 | "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", 40 | "dev": true, 41 | "dependencies": { 42 | "@babel/types": "^7.5.5", 43 | "jsesc": "^2.5.1", 44 | "lodash": "^4.17.13", 45 | "source-map": "^0.5.0", 46 | "trim-right": "^1.0.1" 47 | } 48 | }, 49 | "node_modules/@babel/helper-function-name": { 50 | "version": "7.1.0", 51 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", 52 | "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", 53 | "dev": true, 54 | "dependencies": { 55 | "@babel/helper-get-function-arity": "^7.0.0", 56 | "@babel/template": "^7.1.0", 57 | "@babel/types": "^7.0.0" 58 | } 59 | }, 60 | "node_modules/@babel/helper-get-function-arity": { 61 | "version": "7.0.0", 62 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", 63 | "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", 64 | "dev": true, 65 | "dependencies": { 66 | "@babel/types": "^7.0.0" 67 | } 68 | }, 69 | "node_modules/@babel/helper-split-export-declaration": { 70 | "version": "7.4.4", 71 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", 72 | "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", 73 | "dev": true, 74 | "dependencies": { 75 | "@babel/types": "^7.4.4" 76 | } 77 | }, 78 | "node_modules/@babel/highlight": { 79 | "version": "7.5.0", 80 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", 81 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", 82 | "dev": true, 83 | "dependencies": { 84 | "chalk": "^2.0.0", 85 | "esutils": "^2.0.2", 86 | "js-tokens": "^4.0.0" 87 | } 88 | }, 89 | "node_modules/@babel/parser": { 90 | "version": "7.5.5", 91 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", 92 | "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", 93 | "dev": true, 94 | "bin": { 95 | "parser": "bin/babel-parser.js" 96 | }, 97 | "engines": { 98 | "node": ">=6.0.0" 99 | } 100 | }, 101 | "node_modules/@babel/template": { 102 | "version": "7.4.4", 103 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", 104 | "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", 105 | "dev": true, 106 | "dependencies": { 107 | "@babel/code-frame": "^7.0.0", 108 | "@babel/parser": "^7.4.4", 109 | "@babel/types": "^7.4.4" 110 | } 111 | }, 112 | "node_modules/@babel/traverse": { 113 | "version": "7.5.5", 114 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", 115 | "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", 116 | "dev": true, 117 | "dependencies": { 118 | "@babel/code-frame": "^7.5.5", 119 | "@babel/generator": "^7.5.5", 120 | "@babel/helper-function-name": "^7.1.0", 121 | "@babel/helper-split-export-declaration": "^7.4.4", 122 | "@babel/parser": "^7.5.5", 123 | "@babel/types": "^7.5.5", 124 | "debug": "^4.1.0", 125 | "globals": "^11.1.0", 126 | "lodash": "^4.17.13" 127 | } 128 | }, 129 | "node_modules/@babel/types": { 130 | "version": "7.5.5", 131 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", 132 | "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", 133 | "dev": true, 134 | "dependencies": { 135 | "esutils": "^2.0.2", 136 | "lodash": "^4.17.13", 137 | "to-fast-properties": "^2.0.0" 138 | } 139 | }, 140 | "node_modules/ajv": { 141 | "version": "6.12.6", 142 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 143 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 144 | "dev": true, 145 | "dependencies": { 146 | "fast-deep-equal": "^3.1.1", 147 | "fast-json-stable-stringify": "^2.0.0", 148 | "json-schema-traverse": "^0.4.1", 149 | "uri-js": "^4.2.2" 150 | }, 151 | "funding": { 152 | "type": "github", 153 | "url": "https://github.com/sponsors/epoberezkin" 154 | } 155 | }, 156 | "node_modules/ansi-regex": { 157 | "version": "4.1.1", 158 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", 159 | "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", 160 | "dev": true, 161 | "engines": { 162 | "node": ">=6" 163 | } 164 | }, 165 | "node_modules/ansi-styles": { 166 | "version": "3.2.1", 167 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 168 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 169 | "dev": true, 170 | "dependencies": { 171 | "color-convert": "^1.9.0" 172 | }, 173 | "engines": { 174 | "node": ">=4" 175 | } 176 | }, 177 | "node_modules/append-transform": { 178 | "version": "1.0.0", 179 | "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", 180 | "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", 181 | "dev": true, 182 | "dependencies": { 183 | "default-require-extensions": "^2.0.0" 184 | }, 185 | "engines": { 186 | "node": ">=4" 187 | } 188 | }, 189 | "node_modules/archy": { 190 | "version": "1.0.0", 191 | "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", 192 | "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", 193 | "dev": true 194 | }, 195 | "node_modules/argparse": { 196 | "version": "1.0.10", 197 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 198 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 199 | "dev": true, 200 | "dependencies": { 201 | "sprintf-js": "~1.0.2" 202 | } 203 | }, 204 | "node_modules/asn1": { 205 | "version": "0.2.6", 206 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", 207 | "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", 208 | "dev": true, 209 | "dependencies": { 210 | "safer-buffer": "~2.1.0" 211 | } 212 | }, 213 | "node_modules/assert-plus": { 214 | "version": "1.0.0", 215 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 216 | "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", 217 | "dev": true, 218 | "engines": { 219 | "node": ">=0.8" 220 | } 221 | }, 222 | "node_modules/asynckit": { 223 | "version": "0.4.0", 224 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 225 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 226 | "dev": true 227 | }, 228 | "node_modules/aws-sign2": { 229 | "version": "0.7.0", 230 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 231 | "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", 232 | "dev": true, 233 | "engines": { 234 | "node": "*" 235 | } 236 | }, 237 | "node_modules/aws4": { 238 | "version": "1.12.0", 239 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", 240 | "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", 241 | "dev": true 242 | }, 243 | "node_modules/balanced-match": { 244 | "version": "1.0.0", 245 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 246 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 247 | "dev": true 248 | }, 249 | "node_modules/bcrypt-pbkdf": { 250 | "version": "1.0.2", 251 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 252 | "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", 253 | "dev": true, 254 | "dependencies": { 255 | "tweetnacl": "^0.14.3" 256 | } 257 | }, 258 | "node_modules/brace-expansion": { 259 | "version": "1.1.11", 260 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 261 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 262 | "dev": true, 263 | "dependencies": { 264 | "balanced-match": "^1.0.0", 265 | "concat-map": "0.0.1" 266 | } 267 | }, 268 | "node_modules/caching-transform": { 269 | "version": "3.0.2", 270 | "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", 271 | "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", 272 | "dev": true, 273 | "dependencies": { 274 | "hasha": "^3.0.0", 275 | "make-dir": "^2.0.0", 276 | "package-hash": "^3.0.0", 277 | "write-file-atomic": "^2.4.2" 278 | }, 279 | "engines": { 280 | "node": ">=6" 281 | } 282 | }, 283 | "node_modules/camelcase": { 284 | "version": "5.3.1", 285 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 286 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 287 | "dev": true, 288 | "engines": { 289 | "node": ">=6" 290 | } 291 | }, 292 | "node_modules/caseless": { 293 | "version": "0.12.0", 294 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 295 | "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", 296 | "dev": true 297 | }, 298 | "node_modules/chalk": { 299 | "version": "2.4.2", 300 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 301 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 302 | "dev": true, 303 | "dependencies": { 304 | "ansi-styles": "^3.2.1", 305 | "escape-string-regexp": "^1.0.5", 306 | "supports-color": "^5.3.0" 307 | }, 308 | "engines": { 309 | "node": ">=4" 310 | } 311 | }, 312 | "node_modules/cliui": { 313 | "version": "5.0.0", 314 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 315 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 316 | "dev": true, 317 | "dependencies": { 318 | "string-width": "^3.1.0", 319 | "strip-ansi": "^5.2.0", 320 | "wrap-ansi": "^5.1.0" 321 | } 322 | }, 323 | "node_modules/coffeescript": { 324 | "version": "1.12.7", 325 | "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz", 326 | "integrity": "sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA==", 327 | "dev": true, 328 | "bin": { 329 | "cake": "bin/cake", 330 | "coffee": "bin/coffee" 331 | }, 332 | "engines": { 333 | "node": ">=0.8.0" 334 | } 335 | }, 336 | "node_modules/color-convert": { 337 | "version": "1.9.3", 338 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 339 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 340 | "dev": true, 341 | "dependencies": { 342 | "color-name": "1.1.3" 343 | } 344 | }, 345 | "node_modules/color-name": { 346 | "version": "1.1.3", 347 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 348 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 349 | "dev": true 350 | }, 351 | "node_modules/combined-stream": { 352 | "version": "1.0.8", 353 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 354 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 355 | "dev": true, 356 | "dependencies": { 357 | "delayed-stream": "~1.0.0" 358 | }, 359 | "engines": { 360 | "node": ">= 0.8" 361 | } 362 | }, 363 | "node_modules/commander": { 364 | "version": "3.0.0", 365 | "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.0.tgz", 366 | "integrity": "sha512-pl3QrGOBa9RZaslQiqnnKX2J068wcQw7j9AIaBQ9/JEp5RY6je4jKTImg0Bd+rpoONSe7GUFSgkxLeo17m3Pow==", 367 | "dev": true 368 | }, 369 | "node_modules/commondir": { 370 | "version": "1.0.1", 371 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 372 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 373 | "dev": true 374 | }, 375 | "node_modules/concat-map": { 376 | "version": "0.0.1", 377 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 378 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 379 | "dev": true 380 | }, 381 | "node_modules/convert-source-map": { 382 | "version": "1.6.0", 383 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", 384 | "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", 385 | "dev": true, 386 | "dependencies": { 387 | "safe-buffer": "~5.1.1" 388 | } 389 | }, 390 | "node_modules/convert-source-map/node_modules/safe-buffer": { 391 | "version": "5.1.2", 392 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 393 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 394 | "dev": true 395 | }, 396 | "node_modules/core-util-is": { 397 | "version": "1.0.2", 398 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 399 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", 400 | "dev": true 401 | }, 402 | "node_modules/coveralls": { 403 | "version": "3.1.1", 404 | "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", 405 | "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", 406 | "dev": true, 407 | "dependencies": { 408 | "js-yaml": "^3.13.1", 409 | "lcov-parse": "^1.0.0", 410 | "log-driver": "^1.2.7", 411 | "minimist": "^1.2.5", 412 | "request": "^2.88.2" 413 | }, 414 | "bin": { 415 | "coveralls": "bin/coveralls.js" 416 | }, 417 | "engines": { 418 | "node": ">=6" 419 | } 420 | }, 421 | "node_modules/cp-file": { 422 | "version": "6.2.0", 423 | "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", 424 | "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", 425 | "dev": true, 426 | "dependencies": { 427 | "graceful-fs": "^4.1.2", 428 | "make-dir": "^2.0.0", 429 | "nested-error-stacks": "^2.0.0", 430 | "pify": "^4.0.1", 431 | "safe-buffer": "^5.0.1" 432 | }, 433 | "engines": { 434 | "node": ">=6" 435 | } 436 | }, 437 | "node_modules/cross-spawn": { 438 | "version": "4.0.2", 439 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", 440 | "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", 441 | "dev": true, 442 | "dependencies": { 443 | "lru-cache": "^4.0.1", 444 | "which": "^1.2.9" 445 | } 446 | }, 447 | "node_modules/dashdash": { 448 | "version": "1.14.1", 449 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 450 | "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", 451 | "dev": true, 452 | "dependencies": { 453 | "assert-plus": "^1.0.0" 454 | }, 455 | "engines": { 456 | "node": ">=0.10" 457 | } 458 | }, 459 | "node_modules/debug": { 460 | "version": "4.1.1", 461 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 462 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 463 | "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", 464 | "dev": true, 465 | "dependencies": { 466 | "ms": "^2.1.1" 467 | } 468 | }, 469 | "node_modules/decamelize": { 470 | "version": "1.2.0", 471 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 472 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 473 | "dev": true, 474 | "engines": { 475 | "node": ">=0.10.0" 476 | } 477 | }, 478 | "node_modules/default-require-extensions": { 479 | "version": "2.0.0", 480 | "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", 481 | "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", 482 | "dev": true, 483 | "dependencies": { 484 | "strip-bom": "^3.0.0" 485 | }, 486 | "engines": { 487 | "node": ">=4" 488 | } 489 | }, 490 | "node_modules/delayed-stream": { 491 | "version": "1.0.0", 492 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 493 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 494 | "dev": true, 495 | "engines": { 496 | "node": ">=0.4.0" 497 | } 498 | }, 499 | "node_modules/diff": { 500 | "version": "4.0.1", 501 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", 502 | "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", 503 | "dev": true, 504 | "engines": { 505 | "node": ">=0.3.1" 506 | } 507 | }, 508 | "node_modules/docco": { 509 | "version": "0.8.0", 510 | "resolved": "https://registry.npmjs.org/docco/-/docco-0.8.0.tgz", 511 | "integrity": "sha512-QcWBDnnGaT+rgC0wqynznXv0/4hd6nAFdWNs2fN4FvkH2yAnCYVeRU7GIZXNCeUQ955Lufq+TmZcSXiBa1cGQQ==", 512 | "dev": true, 513 | "dependencies": { 514 | "commander": ">= 0.5.2", 515 | "fs-extra": ">= 0.6.0", 516 | "highlight.js": ">= 8.0.x", 517 | "marked": ">= 0.2.7", 518 | "underscore": ">= 1.0.0" 519 | }, 520 | "bin": { 521 | "docco": "bin/docco" 522 | }, 523 | "engines": { 524 | "node": ">=0.2.0" 525 | } 526 | }, 527 | "node_modules/ecc-jsbn": { 528 | "version": "0.1.2", 529 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 530 | "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", 531 | "dev": true, 532 | "dependencies": { 533 | "jsbn": "~0.1.0", 534 | "safer-buffer": "^2.1.0" 535 | } 536 | }, 537 | "node_modules/emoji-regex": { 538 | "version": "7.0.3", 539 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 540 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 541 | "dev": true 542 | }, 543 | "node_modules/error-ex": { 544 | "version": "1.3.2", 545 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 546 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 547 | "dev": true, 548 | "dependencies": { 549 | "is-arrayish": "^0.2.1" 550 | } 551 | }, 552 | "node_modules/es6-error": { 553 | "version": "4.1.1", 554 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 555 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 556 | "dev": true 557 | }, 558 | "node_modules/escape-string-regexp": { 559 | "version": "1.0.5", 560 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 561 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 562 | "dev": true, 563 | "engines": { 564 | "node": ">=0.8.0" 565 | } 566 | }, 567 | "node_modules/esprima": { 568 | "version": "4.0.1", 569 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 570 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 571 | "dev": true, 572 | "bin": { 573 | "esparse": "bin/esparse.js", 574 | "esvalidate": "bin/esvalidate.js" 575 | }, 576 | "engines": { 577 | "node": ">=4" 578 | } 579 | }, 580 | "node_modules/esutils": { 581 | "version": "2.0.3", 582 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 583 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 584 | "dev": true, 585 | "engines": { 586 | "node": ">=0.10.0" 587 | } 588 | }, 589 | "node_modules/extend": { 590 | "version": "3.0.2", 591 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 592 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 593 | "dev": true 594 | }, 595 | "node_modules/extsprintf": { 596 | "version": "1.3.0", 597 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 598 | "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", 599 | "dev": true, 600 | "engines": [ 601 | "node >=0.6.0" 602 | ] 603 | }, 604 | "node_modules/fast-deep-equal": { 605 | "version": "3.1.3", 606 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 607 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 608 | "dev": true 609 | }, 610 | "node_modules/fast-json-stable-stringify": { 611 | "version": "2.1.0", 612 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 613 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 614 | "dev": true 615 | }, 616 | "node_modules/find-cache-dir": { 617 | "version": "2.1.0", 618 | "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", 619 | "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", 620 | "dev": true, 621 | "dependencies": { 622 | "commondir": "^1.0.1", 623 | "make-dir": "^2.0.0", 624 | "pkg-dir": "^3.0.0" 625 | }, 626 | "engines": { 627 | "node": ">=6" 628 | } 629 | }, 630 | "node_modules/find-up": { 631 | "version": "3.0.0", 632 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 633 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 634 | "dev": true, 635 | "dependencies": { 636 | "locate-path": "^3.0.0" 637 | }, 638 | "engines": { 639 | "node": ">=6" 640 | } 641 | }, 642 | "node_modules/foreground-child": { 643 | "version": "1.5.6", 644 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", 645 | "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", 646 | "dev": true, 647 | "dependencies": { 648 | "cross-spawn": "^4", 649 | "signal-exit": "^3.0.0" 650 | } 651 | }, 652 | "node_modules/forever-agent": { 653 | "version": "0.6.1", 654 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 655 | "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", 656 | "dev": true, 657 | "engines": { 658 | "node": "*" 659 | } 660 | }, 661 | "node_modules/form-data": { 662 | "version": "2.3.3", 663 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 664 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 665 | "dev": true, 666 | "dependencies": { 667 | "asynckit": "^0.4.0", 668 | "combined-stream": "^1.0.6", 669 | "mime-types": "^2.1.12" 670 | }, 671 | "engines": { 672 | "node": ">= 0.12" 673 | } 674 | }, 675 | "node_modules/fs-extra": { 676 | "version": "8.1.0", 677 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 678 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 679 | "dev": true, 680 | "dependencies": { 681 | "graceful-fs": "^4.2.0", 682 | "jsonfile": "^4.0.0", 683 | "universalify": "^0.1.0" 684 | }, 685 | "engines": { 686 | "node": ">=6 <7 || >=8" 687 | } 688 | }, 689 | "node_modules/fs.realpath": { 690 | "version": "1.0.0", 691 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 692 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 693 | "dev": true 694 | }, 695 | "node_modules/get-caller-file": { 696 | "version": "2.0.5", 697 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 698 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 699 | "dev": true, 700 | "engines": { 701 | "node": "6.* || 8.* || >= 10.*" 702 | } 703 | }, 704 | "node_modules/getpass": { 705 | "version": "0.1.7", 706 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 707 | "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", 708 | "dev": true, 709 | "dependencies": { 710 | "assert-plus": "^1.0.0" 711 | } 712 | }, 713 | "node_modules/glob": { 714 | "version": "7.1.4", 715 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", 716 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 717 | "dev": true, 718 | "dependencies": { 719 | "fs.realpath": "^1.0.0", 720 | "inflight": "^1.0.4", 721 | "inherits": "2", 722 | "minimatch": "^3.0.4", 723 | "once": "^1.3.0", 724 | "path-is-absolute": "^1.0.0" 725 | }, 726 | "engines": { 727 | "node": "*" 728 | } 729 | }, 730 | "node_modules/globals": { 731 | "version": "11.12.0", 732 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 733 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 734 | "dev": true, 735 | "engines": { 736 | "node": ">=4" 737 | } 738 | }, 739 | "node_modules/graceful-fs": { 740 | "version": "4.2.2", 741 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", 742 | "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", 743 | "dev": true 744 | }, 745 | "node_modules/handlebars": { 746 | "version": "4.7.7", 747 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", 748 | "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", 749 | "dev": true, 750 | "dependencies": { 751 | "minimist": "^1.2.5", 752 | "neo-async": "^2.6.0", 753 | "source-map": "^0.6.1", 754 | "wordwrap": "^1.0.0" 755 | }, 756 | "bin": { 757 | "handlebars": "bin/handlebars" 758 | }, 759 | "engines": { 760 | "node": ">=0.4.7" 761 | }, 762 | "optionalDependencies": { 763 | "uglify-js": "^3.1.4" 764 | } 765 | }, 766 | "node_modules/handlebars/node_modules/source-map": { 767 | "version": "0.6.1", 768 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 769 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 770 | "dev": true, 771 | "engines": { 772 | "node": ">=0.10.0" 773 | } 774 | }, 775 | "node_modules/har-schema": { 776 | "version": "2.0.0", 777 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 778 | "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", 779 | "dev": true, 780 | "engines": { 781 | "node": ">=4" 782 | } 783 | }, 784 | "node_modules/har-validator": { 785 | "version": "5.1.5", 786 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 787 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 788 | "deprecated": "this library is no longer supported", 789 | "dev": true, 790 | "dependencies": { 791 | "ajv": "^6.12.3", 792 | "har-schema": "^2.0.0" 793 | }, 794 | "engines": { 795 | "node": ">=6" 796 | } 797 | }, 798 | "node_modules/has-flag": { 799 | "version": "3.0.0", 800 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 801 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 802 | "dev": true, 803 | "engines": { 804 | "node": ">=4" 805 | } 806 | }, 807 | "node_modules/hasha": { 808 | "version": "3.0.0", 809 | "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", 810 | "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", 811 | "dev": true, 812 | "dependencies": { 813 | "is-stream": "^1.0.1" 814 | }, 815 | "engines": { 816 | "node": ">=4" 817 | } 818 | }, 819 | "node_modules/highlight.js": { 820 | "version": "11.7.0", 821 | "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz", 822 | "integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ==", 823 | "dev": true, 824 | "engines": { 825 | "node": ">=12.0.0" 826 | } 827 | }, 828 | "node_modules/hosted-git-info": { 829 | "version": "2.8.9", 830 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", 831 | "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", 832 | "dev": true 833 | }, 834 | "node_modules/http-signature": { 835 | "version": "1.2.0", 836 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 837 | "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", 838 | "dev": true, 839 | "dependencies": { 840 | "assert-plus": "^1.0.0", 841 | "jsprim": "^1.2.2", 842 | "sshpk": "^1.7.0" 843 | }, 844 | "engines": { 845 | "node": ">=0.8", 846 | "npm": ">=1.3.7" 847 | } 848 | }, 849 | "node_modules/imurmurhash": { 850 | "version": "0.1.4", 851 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 852 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 853 | "dev": true, 854 | "engines": { 855 | "node": ">=0.8.19" 856 | } 857 | }, 858 | "node_modules/inflight": { 859 | "version": "1.0.6", 860 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 861 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 862 | "dev": true, 863 | "dependencies": { 864 | "once": "^1.3.0", 865 | "wrappy": "1" 866 | } 867 | }, 868 | "node_modules/inherits": { 869 | "version": "2.0.4", 870 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 871 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 872 | "dev": true 873 | }, 874 | "node_modules/is-arrayish": { 875 | "version": "0.2.1", 876 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 877 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 878 | "dev": true 879 | }, 880 | "node_modules/is-fullwidth-code-point": { 881 | "version": "2.0.0", 882 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 883 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 884 | "dev": true, 885 | "engines": { 886 | "node": ">=4" 887 | } 888 | }, 889 | "node_modules/is-stream": { 890 | "version": "1.1.0", 891 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 892 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 893 | "dev": true, 894 | "engines": { 895 | "node": ">=0.10.0" 896 | } 897 | }, 898 | "node_modules/is-typedarray": { 899 | "version": "1.0.0", 900 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 901 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", 902 | "dev": true 903 | }, 904 | "node_modules/isexe": { 905 | "version": "2.0.0", 906 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 907 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 908 | "dev": true 909 | }, 910 | "node_modules/isstream": { 911 | "version": "0.1.2", 912 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 913 | "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", 914 | "dev": true 915 | }, 916 | "node_modules/istanbul-lib-coverage": { 917 | "version": "2.0.5", 918 | "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", 919 | "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", 920 | "dev": true, 921 | "engines": { 922 | "node": ">=6" 923 | } 924 | }, 925 | "node_modules/istanbul-lib-hook": { 926 | "version": "2.0.7", 927 | "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", 928 | "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", 929 | "dev": true, 930 | "dependencies": { 931 | "append-transform": "^1.0.0" 932 | }, 933 | "engines": { 934 | "node": ">=6" 935 | } 936 | }, 937 | "node_modules/istanbul-lib-instrument": { 938 | "version": "3.3.0", 939 | "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", 940 | "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", 941 | "dev": true, 942 | "dependencies": { 943 | "@babel/generator": "^7.4.0", 944 | "@babel/parser": "^7.4.3", 945 | "@babel/template": "^7.4.0", 946 | "@babel/traverse": "^7.4.3", 947 | "@babel/types": "^7.4.0", 948 | "istanbul-lib-coverage": "^2.0.5", 949 | "semver": "^6.0.0" 950 | }, 951 | "engines": { 952 | "node": ">=6" 953 | } 954 | }, 955 | "node_modules/istanbul-lib-instrument/node_modules/semver": { 956 | "version": "6.3.0", 957 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 958 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 959 | "dev": true, 960 | "bin": { 961 | "semver": "bin/semver.js" 962 | } 963 | }, 964 | "node_modules/istanbul-lib-report": { 965 | "version": "2.0.8", 966 | "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", 967 | "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", 968 | "dev": true, 969 | "dependencies": { 970 | "istanbul-lib-coverage": "^2.0.5", 971 | "make-dir": "^2.1.0", 972 | "supports-color": "^6.1.0" 973 | }, 974 | "engines": { 975 | "node": ">=6" 976 | } 977 | }, 978 | "node_modules/istanbul-lib-report/node_modules/supports-color": { 979 | "version": "6.1.0", 980 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", 981 | "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", 982 | "dev": true, 983 | "dependencies": { 984 | "has-flag": "^3.0.0" 985 | }, 986 | "engines": { 987 | "node": ">=6" 988 | } 989 | }, 990 | "node_modules/istanbul-lib-source-maps": { 991 | "version": "3.0.6", 992 | "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", 993 | "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", 994 | "dev": true, 995 | "dependencies": { 996 | "debug": "^4.1.1", 997 | "istanbul-lib-coverage": "^2.0.5", 998 | "make-dir": "^2.1.0", 999 | "rimraf": "^2.6.3", 1000 | "source-map": "^0.6.1" 1001 | }, 1002 | "engines": { 1003 | "node": ">=6" 1004 | } 1005 | }, 1006 | "node_modules/istanbul-lib-source-maps/node_modules/source-map": { 1007 | "version": "0.6.1", 1008 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1009 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1010 | "dev": true, 1011 | "engines": { 1012 | "node": ">=0.10.0" 1013 | } 1014 | }, 1015 | "node_modules/istanbul-reports": { 1016 | "version": "2.2.6", 1017 | "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", 1018 | "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", 1019 | "dev": true, 1020 | "dependencies": { 1021 | "handlebars": "^4.1.2" 1022 | }, 1023 | "engines": { 1024 | "node": ">=6" 1025 | } 1026 | }, 1027 | "node_modules/js-tokens": { 1028 | "version": "4.0.0", 1029 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1030 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1031 | "dev": true 1032 | }, 1033 | "node_modules/js-yaml": { 1034 | "version": "3.13.1", 1035 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1036 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1037 | "dev": true, 1038 | "dependencies": { 1039 | "argparse": "^1.0.7", 1040 | "esprima": "^4.0.0" 1041 | }, 1042 | "bin": { 1043 | "js-yaml": "bin/js-yaml.js" 1044 | } 1045 | }, 1046 | "node_modules/jsbn": { 1047 | "version": "0.1.1", 1048 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1049 | "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", 1050 | "dev": true 1051 | }, 1052 | "node_modules/jsesc": { 1053 | "version": "2.5.2", 1054 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 1055 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 1056 | "dev": true, 1057 | "bin": { 1058 | "jsesc": "bin/jsesc" 1059 | }, 1060 | "engines": { 1061 | "node": ">=4" 1062 | } 1063 | }, 1064 | "node_modules/json-parse-better-errors": { 1065 | "version": "1.0.2", 1066 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", 1067 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", 1068 | "dev": true 1069 | }, 1070 | "node_modules/json-schema": { 1071 | "version": "0.4.0", 1072 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 1073 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", 1074 | "dev": true 1075 | }, 1076 | "node_modules/json-schema-traverse": { 1077 | "version": "0.4.1", 1078 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1079 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1080 | "dev": true 1081 | }, 1082 | "node_modules/json-stringify-safe": { 1083 | "version": "5.0.1", 1084 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1085 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", 1086 | "dev": true 1087 | }, 1088 | "node_modules/jsonfile": { 1089 | "version": "4.0.0", 1090 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 1091 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 1092 | "dev": true, 1093 | "optionalDependencies": { 1094 | "graceful-fs": "^4.1.6" 1095 | } 1096 | }, 1097 | "node_modules/jsprim": { 1098 | "version": "1.4.2", 1099 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", 1100 | "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", 1101 | "dev": true, 1102 | "dependencies": { 1103 | "assert-plus": "1.0.0", 1104 | "extsprintf": "1.3.0", 1105 | "json-schema": "0.4.0", 1106 | "verror": "1.10.0" 1107 | }, 1108 | "engines": { 1109 | "node": ">=0.6.0" 1110 | } 1111 | }, 1112 | "node_modules/lcov-parse": { 1113 | "version": "1.0.0", 1114 | "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", 1115 | "integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==", 1116 | "dev": true, 1117 | "bin": { 1118 | "lcov-parse": "bin/cli.js" 1119 | } 1120 | }, 1121 | "node_modules/load-json-file": { 1122 | "version": "4.0.0", 1123 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", 1124 | "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", 1125 | "dev": true, 1126 | "dependencies": { 1127 | "graceful-fs": "^4.1.2", 1128 | "parse-json": "^4.0.0", 1129 | "pify": "^3.0.0", 1130 | "strip-bom": "^3.0.0" 1131 | }, 1132 | "engines": { 1133 | "node": ">=4" 1134 | } 1135 | }, 1136 | "node_modules/load-json-file/node_modules/pify": { 1137 | "version": "3.0.0", 1138 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1139 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 1140 | "dev": true, 1141 | "engines": { 1142 | "node": ">=4" 1143 | } 1144 | }, 1145 | "node_modules/locate-path": { 1146 | "version": "3.0.0", 1147 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1148 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1149 | "dev": true, 1150 | "dependencies": { 1151 | "p-locate": "^3.0.0", 1152 | "path-exists": "^3.0.0" 1153 | }, 1154 | "engines": { 1155 | "node": ">=6" 1156 | } 1157 | }, 1158 | "node_modules/lodash": { 1159 | "version": "4.17.21", 1160 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1161 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1162 | "dev": true 1163 | }, 1164 | "node_modules/lodash.flattendeep": { 1165 | "version": "4.4.0", 1166 | "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", 1167 | "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", 1168 | "dev": true 1169 | }, 1170 | "node_modules/log-driver": { 1171 | "version": "1.2.7", 1172 | "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", 1173 | "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", 1174 | "dev": true, 1175 | "engines": { 1176 | "node": ">=0.8.6" 1177 | } 1178 | }, 1179 | "node_modules/lru-cache": { 1180 | "version": "4.1.5", 1181 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 1182 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 1183 | "dev": true, 1184 | "dependencies": { 1185 | "pseudomap": "^1.0.2", 1186 | "yallist": "^2.1.2" 1187 | } 1188 | }, 1189 | "node_modules/make-dir": { 1190 | "version": "2.1.0", 1191 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", 1192 | "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", 1193 | "dev": true, 1194 | "dependencies": { 1195 | "pify": "^4.0.1", 1196 | "semver": "^5.6.0" 1197 | }, 1198 | "engines": { 1199 | "node": ">=6" 1200 | } 1201 | }, 1202 | "node_modules/marked": { 1203 | "version": "4.3.0", 1204 | "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", 1205 | "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", 1206 | "dev": true, 1207 | "bin": { 1208 | "marked": "bin/marked.js" 1209 | }, 1210 | "engines": { 1211 | "node": ">= 12" 1212 | } 1213 | }, 1214 | "node_modules/merge-source-map": { 1215 | "version": "1.1.0", 1216 | "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", 1217 | "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", 1218 | "dev": true, 1219 | "dependencies": { 1220 | "source-map": "^0.6.1" 1221 | } 1222 | }, 1223 | "node_modules/merge-source-map/node_modules/source-map": { 1224 | "version": "0.6.1", 1225 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1226 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1227 | "dev": true, 1228 | "engines": { 1229 | "node": ">=0.10.0" 1230 | } 1231 | }, 1232 | "node_modules/mime-db": { 1233 | "version": "1.52.0", 1234 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1235 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1236 | "dev": true, 1237 | "engines": { 1238 | "node": ">= 0.6" 1239 | } 1240 | }, 1241 | "node_modules/mime-types": { 1242 | "version": "2.1.35", 1243 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1244 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1245 | "dev": true, 1246 | "dependencies": { 1247 | "mime-db": "1.52.0" 1248 | }, 1249 | "engines": { 1250 | "node": ">= 0.6" 1251 | } 1252 | }, 1253 | "node_modules/minimatch": { 1254 | "version": "3.1.2", 1255 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1256 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1257 | "dev": true, 1258 | "dependencies": { 1259 | "brace-expansion": "^1.1.7" 1260 | }, 1261 | "engines": { 1262 | "node": "*" 1263 | } 1264 | }, 1265 | "node_modules/minimist": { 1266 | "version": "1.2.8", 1267 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1268 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1269 | "dev": true, 1270 | "funding": { 1271 | "url": "https://github.com/sponsors/ljharb" 1272 | } 1273 | }, 1274 | "node_modules/mkdirp": { 1275 | "version": "0.5.6", 1276 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 1277 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 1278 | "dev": true, 1279 | "dependencies": { 1280 | "minimist": "^1.2.6" 1281 | }, 1282 | "bin": { 1283 | "mkdirp": "bin/cmd.js" 1284 | } 1285 | }, 1286 | "node_modules/ms": { 1287 | "version": "2.1.2", 1288 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1289 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1290 | "dev": true 1291 | }, 1292 | "node_modules/neo-async": { 1293 | "version": "2.6.1", 1294 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", 1295 | "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", 1296 | "dev": true 1297 | }, 1298 | "node_modules/nested-error-stacks": { 1299 | "version": "2.1.0", 1300 | "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", 1301 | "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", 1302 | "dev": true 1303 | }, 1304 | "node_modules/normalize-package-data": { 1305 | "version": "2.5.0", 1306 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 1307 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 1308 | "dev": true, 1309 | "dependencies": { 1310 | "hosted-git-info": "^2.1.4", 1311 | "resolve": "^1.10.0", 1312 | "semver": "2 || 3 || 4 || 5", 1313 | "validate-npm-package-license": "^3.0.1" 1314 | } 1315 | }, 1316 | "node_modules/nyc": { 1317 | "version": "14.1.1", 1318 | "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", 1319 | "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", 1320 | "dev": true, 1321 | "dependencies": { 1322 | "archy": "^1.0.0", 1323 | "caching-transform": "^3.0.2", 1324 | "convert-source-map": "^1.6.0", 1325 | "cp-file": "^6.2.0", 1326 | "find-cache-dir": "^2.1.0", 1327 | "find-up": "^3.0.0", 1328 | "foreground-child": "^1.5.6", 1329 | "glob": "^7.1.3", 1330 | "istanbul-lib-coverage": "^2.0.5", 1331 | "istanbul-lib-hook": "^2.0.7", 1332 | "istanbul-lib-instrument": "^3.3.0", 1333 | "istanbul-lib-report": "^2.0.8", 1334 | "istanbul-lib-source-maps": "^3.0.6", 1335 | "istanbul-reports": "^2.2.4", 1336 | "js-yaml": "^3.13.1", 1337 | "make-dir": "^2.1.0", 1338 | "merge-source-map": "^1.1.0", 1339 | "resolve-from": "^4.0.0", 1340 | "rimraf": "^2.6.3", 1341 | "signal-exit": "^3.0.2", 1342 | "spawn-wrap": "^1.4.2", 1343 | "test-exclude": "^5.2.3", 1344 | "uuid": "^3.3.2", 1345 | "yargs": "^13.2.2", 1346 | "yargs-parser": "^13.0.0" 1347 | }, 1348 | "bin": { 1349 | "nyc": "bin/nyc.js" 1350 | }, 1351 | "engines": { 1352 | "node": ">=6" 1353 | } 1354 | }, 1355 | "node_modules/oauth-sign": { 1356 | "version": "0.9.0", 1357 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1358 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1359 | "dev": true, 1360 | "engines": { 1361 | "node": "*" 1362 | } 1363 | }, 1364 | "node_modules/once": { 1365 | "version": "1.4.0", 1366 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1367 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1368 | "dev": true, 1369 | "dependencies": { 1370 | "wrappy": "1" 1371 | } 1372 | }, 1373 | "node_modules/os-homedir": { 1374 | "version": "1.0.2", 1375 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 1376 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", 1377 | "dev": true, 1378 | "engines": { 1379 | "node": ">=0.10.0" 1380 | } 1381 | }, 1382 | "node_modules/p-limit": { 1383 | "version": "2.2.1", 1384 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", 1385 | "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", 1386 | "dev": true, 1387 | "dependencies": { 1388 | "p-try": "^2.0.0" 1389 | }, 1390 | "engines": { 1391 | "node": ">=6" 1392 | } 1393 | }, 1394 | "node_modules/p-locate": { 1395 | "version": "3.0.0", 1396 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1397 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1398 | "dev": true, 1399 | "dependencies": { 1400 | "p-limit": "^2.0.0" 1401 | }, 1402 | "engines": { 1403 | "node": ">=6" 1404 | } 1405 | }, 1406 | "node_modules/p-try": { 1407 | "version": "2.2.0", 1408 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1409 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1410 | "dev": true, 1411 | "engines": { 1412 | "node": ">=6" 1413 | } 1414 | }, 1415 | "node_modules/package-hash": { 1416 | "version": "3.0.0", 1417 | "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", 1418 | "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", 1419 | "dev": true, 1420 | "dependencies": { 1421 | "graceful-fs": "^4.1.15", 1422 | "hasha": "^3.0.0", 1423 | "lodash.flattendeep": "^4.4.0", 1424 | "release-zalgo": "^1.0.0" 1425 | }, 1426 | "engines": { 1427 | "node": ">=6" 1428 | } 1429 | }, 1430 | "node_modules/parse-json": { 1431 | "version": "4.0.0", 1432 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", 1433 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", 1434 | "dev": true, 1435 | "dependencies": { 1436 | "error-ex": "^1.3.1", 1437 | "json-parse-better-errors": "^1.0.1" 1438 | }, 1439 | "engines": { 1440 | "node": ">=4" 1441 | } 1442 | }, 1443 | "node_modules/path-exists": { 1444 | "version": "3.0.0", 1445 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1446 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1447 | "dev": true, 1448 | "engines": { 1449 | "node": ">=4" 1450 | } 1451 | }, 1452 | "node_modules/path-is-absolute": { 1453 | "version": "1.0.1", 1454 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1455 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1456 | "dev": true, 1457 | "engines": { 1458 | "node": ">=0.10.0" 1459 | } 1460 | }, 1461 | "node_modules/path-parse": { 1462 | "version": "1.0.7", 1463 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1464 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1465 | "dev": true 1466 | }, 1467 | "node_modules/path-type": { 1468 | "version": "3.0.0", 1469 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", 1470 | "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", 1471 | "dev": true, 1472 | "dependencies": { 1473 | "pify": "^3.0.0" 1474 | }, 1475 | "engines": { 1476 | "node": ">=4" 1477 | } 1478 | }, 1479 | "node_modules/path-type/node_modules/pify": { 1480 | "version": "3.0.0", 1481 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1482 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 1483 | "dev": true, 1484 | "engines": { 1485 | "node": ">=4" 1486 | } 1487 | }, 1488 | "node_modules/performance-now": { 1489 | "version": "2.1.0", 1490 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1491 | "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", 1492 | "dev": true 1493 | }, 1494 | "node_modules/pify": { 1495 | "version": "4.0.1", 1496 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 1497 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 1498 | "dev": true, 1499 | "engines": { 1500 | "node": ">=6" 1501 | } 1502 | }, 1503 | "node_modules/pkg-dir": { 1504 | "version": "3.0.0", 1505 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", 1506 | "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", 1507 | "dev": true, 1508 | "dependencies": { 1509 | "find-up": "^3.0.0" 1510 | }, 1511 | "engines": { 1512 | "node": ">=6" 1513 | } 1514 | }, 1515 | "node_modules/pseudomap": { 1516 | "version": "1.0.2", 1517 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1518 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 1519 | "dev": true 1520 | }, 1521 | "node_modules/psl": { 1522 | "version": "1.9.0", 1523 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 1524 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", 1525 | "dev": true 1526 | }, 1527 | "node_modules/punycode": { 1528 | "version": "2.3.0", 1529 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 1530 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 1531 | "dev": true, 1532 | "engines": { 1533 | "node": ">=6" 1534 | } 1535 | }, 1536 | "node_modules/qs": { 1537 | "version": "6.5.3", 1538 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", 1539 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", 1540 | "dev": true, 1541 | "engines": { 1542 | "node": ">=0.6" 1543 | } 1544 | }, 1545 | "node_modules/read-pkg": { 1546 | "version": "3.0.0", 1547 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", 1548 | "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", 1549 | "dev": true, 1550 | "dependencies": { 1551 | "load-json-file": "^4.0.0", 1552 | "normalize-package-data": "^2.3.2", 1553 | "path-type": "^3.0.0" 1554 | }, 1555 | "engines": { 1556 | "node": ">=4" 1557 | } 1558 | }, 1559 | "node_modules/read-pkg-up": { 1560 | "version": "4.0.0", 1561 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", 1562 | "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", 1563 | "dev": true, 1564 | "dependencies": { 1565 | "find-up": "^3.0.0", 1566 | "read-pkg": "^3.0.0" 1567 | }, 1568 | "engines": { 1569 | "node": ">=6" 1570 | } 1571 | }, 1572 | "node_modules/release-zalgo": { 1573 | "version": "1.0.0", 1574 | "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", 1575 | "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", 1576 | "dev": true, 1577 | "dependencies": { 1578 | "es6-error": "^4.0.1" 1579 | }, 1580 | "engines": { 1581 | "node": ">=4" 1582 | } 1583 | }, 1584 | "node_modules/request": { 1585 | "version": "2.88.2", 1586 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 1587 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 1588 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", 1589 | "dev": true, 1590 | "dependencies": { 1591 | "aws-sign2": "~0.7.0", 1592 | "aws4": "^1.8.0", 1593 | "caseless": "~0.12.0", 1594 | "combined-stream": "~1.0.6", 1595 | "extend": "~3.0.2", 1596 | "forever-agent": "~0.6.1", 1597 | "form-data": "~2.3.2", 1598 | "har-validator": "~5.1.3", 1599 | "http-signature": "~1.2.0", 1600 | "is-typedarray": "~1.0.0", 1601 | "isstream": "~0.1.2", 1602 | "json-stringify-safe": "~5.0.1", 1603 | "mime-types": "~2.1.19", 1604 | "oauth-sign": "~0.9.0", 1605 | "performance-now": "^2.1.0", 1606 | "qs": "~6.5.2", 1607 | "safe-buffer": "^5.1.2", 1608 | "tough-cookie": "~2.5.0", 1609 | "tunnel-agent": "^0.6.0", 1610 | "uuid": "^3.3.2" 1611 | }, 1612 | "engines": { 1613 | "node": ">= 6" 1614 | } 1615 | }, 1616 | "node_modules/require-directory": { 1617 | "version": "2.1.1", 1618 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1619 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1620 | "dev": true, 1621 | "engines": { 1622 | "node": ">=0.10.0" 1623 | } 1624 | }, 1625 | "node_modules/require-main-filename": { 1626 | "version": "2.0.0", 1627 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1628 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 1629 | "dev": true 1630 | }, 1631 | "node_modules/resolve": { 1632 | "version": "1.12.0", 1633 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", 1634 | "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", 1635 | "dev": true, 1636 | "dependencies": { 1637 | "path-parse": "^1.0.6" 1638 | } 1639 | }, 1640 | "node_modules/resolve-from": { 1641 | "version": "4.0.0", 1642 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1643 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1644 | "dev": true, 1645 | "engines": { 1646 | "node": ">=4" 1647 | } 1648 | }, 1649 | "node_modules/rimraf": { 1650 | "version": "2.7.1", 1651 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 1652 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 1653 | "dev": true, 1654 | "dependencies": { 1655 | "glob": "^7.1.3" 1656 | }, 1657 | "bin": { 1658 | "rimraf": "bin.js" 1659 | } 1660 | }, 1661 | "node_modules/safe-buffer": { 1662 | "version": "5.2.0", 1663 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 1664 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", 1665 | "dev": true 1666 | }, 1667 | "node_modules/safer-buffer": { 1668 | "version": "2.1.2", 1669 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1670 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1671 | "dev": true 1672 | }, 1673 | "node_modules/sax": { 1674 | "version": "1.2.4", 1675 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1676 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 1677 | }, 1678 | "node_modules/semver": { 1679 | "version": "5.7.1", 1680 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1681 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1682 | "dev": true, 1683 | "bin": { 1684 | "semver": "bin/semver" 1685 | } 1686 | }, 1687 | "node_modules/set-blocking": { 1688 | "version": "2.0.0", 1689 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1690 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 1691 | "dev": true 1692 | }, 1693 | "node_modules/signal-exit": { 1694 | "version": "3.0.2", 1695 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1696 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1697 | "dev": true 1698 | }, 1699 | "node_modules/source-map": { 1700 | "version": "0.5.7", 1701 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1702 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1703 | "dev": true, 1704 | "engines": { 1705 | "node": ">=0.10.0" 1706 | } 1707 | }, 1708 | "node_modules/spawn-wrap": { 1709 | "version": "1.4.3", 1710 | "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", 1711 | "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", 1712 | "dev": true, 1713 | "dependencies": { 1714 | "foreground-child": "^1.5.6", 1715 | "mkdirp": "^0.5.0", 1716 | "os-homedir": "^1.0.1", 1717 | "rimraf": "^2.6.2", 1718 | "signal-exit": "^3.0.2", 1719 | "which": "^1.3.0" 1720 | } 1721 | }, 1722 | "node_modules/spdx-correct": { 1723 | "version": "3.1.0", 1724 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", 1725 | "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", 1726 | "dev": true, 1727 | "dependencies": { 1728 | "spdx-expression-parse": "^3.0.0", 1729 | "spdx-license-ids": "^3.0.0" 1730 | } 1731 | }, 1732 | "node_modules/spdx-exceptions": { 1733 | "version": "2.2.0", 1734 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", 1735 | "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", 1736 | "dev": true 1737 | }, 1738 | "node_modules/spdx-expression-parse": { 1739 | "version": "3.0.0", 1740 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", 1741 | "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", 1742 | "dev": true, 1743 | "dependencies": { 1744 | "spdx-exceptions": "^2.1.0", 1745 | "spdx-license-ids": "^3.0.0" 1746 | } 1747 | }, 1748 | "node_modules/spdx-license-ids": { 1749 | "version": "3.0.5", 1750 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", 1751 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", 1752 | "dev": true 1753 | }, 1754 | "node_modules/sprintf-js": { 1755 | "version": "1.0.3", 1756 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1757 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1758 | "dev": true 1759 | }, 1760 | "node_modules/sshpk": { 1761 | "version": "1.17.0", 1762 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", 1763 | "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", 1764 | "dev": true, 1765 | "dependencies": { 1766 | "asn1": "~0.2.3", 1767 | "assert-plus": "^1.0.0", 1768 | "bcrypt-pbkdf": "^1.0.0", 1769 | "dashdash": "^1.12.0", 1770 | "ecc-jsbn": "~0.1.1", 1771 | "getpass": "^0.1.1", 1772 | "jsbn": "~0.1.0", 1773 | "safer-buffer": "^2.0.2", 1774 | "tweetnacl": "~0.14.0" 1775 | }, 1776 | "bin": { 1777 | "sshpk-conv": "bin/sshpk-conv", 1778 | "sshpk-sign": "bin/sshpk-sign", 1779 | "sshpk-verify": "bin/sshpk-verify" 1780 | }, 1781 | "engines": { 1782 | "node": ">=0.10.0" 1783 | } 1784 | }, 1785 | "node_modules/string-width": { 1786 | "version": "3.1.0", 1787 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1788 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1789 | "dev": true, 1790 | "dependencies": { 1791 | "emoji-regex": "^7.0.1", 1792 | "is-fullwidth-code-point": "^2.0.0", 1793 | "strip-ansi": "^5.1.0" 1794 | }, 1795 | "engines": { 1796 | "node": ">=6" 1797 | } 1798 | }, 1799 | "node_modules/strip-ansi": { 1800 | "version": "5.2.0", 1801 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1802 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1803 | "dev": true, 1804 | "dependencies": { 1805 | "ansi-regex": "^4.1.0" 1806 | }, 1807 | "engines": { 1808 | "node": ">=6" 1809 | } 1810 | }, 1811 | "node_modules/strip-bom": { 1812 | "version": "3.0.0", 1813 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1814 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 1815 | "dev": true, 1816 | "engines": { 1817 | "node": ">=4" 1818 | } 1819 | }, 1820 | "node_modules/supports-color": { 1821 | "version": "5.5.0", 1822 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1823 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1824 | "dev": true, 1825 | "dependencies": { 1826 | "has-flag": "^3.0.0" 1827 | }, 1828 | "engines": { 1829 | "node": ">=4" 1830 | } 1831 | }, 1832 | "node_modules/test-exclude": { 1833 | "version": "5.2.3", 1834 | "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", 1835 | "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", 1836 | "dev": true, 1837 | "dependencies": { 1838 | "glob": "^7.1.3", 1839 | "minimatch": "^3.0.4", 1840 | "read-pkg-up": "^4.0.0", 1841 | "require-main-filename": "^2.0.0" 1842 | }, 1843 | "engines": { 1844 | "node": ">=6" 1845 | } 1846 | }, 1847 | "node_modules/to-fast-properties": { 1848 | "version": "2.0.0", 1849 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 1850 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", 1851 | "dev": true, 1852 | "engines": { 1853 | "node": ">=4" 1854 | } 1855 | }, 1856 | "node_modules/tough-cookie": { 1857 | "version": "2.5.0", 1858 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 1859 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 1860 | "dev": true, 1861 | "dependencies": { 1862 | "psl": "^1.1.28", 1863 | "punycode": "^2.1.1" 1864 | }, 1865 | "engines": { 1866 | "node": ">=0.8" 1867 | } 1868 | }, 1869 | "node_modules/trim-right": { 1870 | "version": "1.0.1", 1871 | "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", 1872 | "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", 1873 | "dev": true, 1874 | "engines": { 1875 | "node": ">=0.10.0" 1876 | } 1877 | }, 1878 | "node_modules/tunnel-agent": { 1879 | "version": "0.6.0", 1880 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1881 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 1882 | "dev": true, 1883 | "dependencies": { 1884 | "safe-buffer": "^5.0.1" 1885 | }, 1886 | "engines": { 1887 | "node": "*" 1888 | } 1889 | }, 1890 | "node_modules/tweetnacl": { 1891 | "version": "0.14.5", 1892 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1893 | "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", 1894 | "dev": true 1895 | }, 1896 | "node_modules/uglify-js": { 1897 | "version": "3.6.0", 1898 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", 1899 | "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", 1900 | "dev": true, 1901 | "optional": true, 1902 | "dependencies": { 1903 | "commander": "~2.20.0", 1904 | "source-map": "~0.6.1" 1905 | }, 1906 | "bin": { 1907 | "uglifyjs": "bin/uglifyjs" 1908 | }, 1909 | "engines": { 1910 | "node": ">=0.8.0" 1911 | } 1912 | }, 1913 | "node_modules/uglify-js/node_modules/commander": { 1914 | "version": "2.20.0", 1915 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", 1916 | "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", 1917 | "dev": true, 1918 | "optional": true 1919 | }, 1920 | "node_modules/uglify-js/node_modules/source-map": { 1921 | "version": "0.6.1", 1922 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1923 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1924 | "dev": true, 1925 | "optional": true, 1926 | "engines": { 1927 | "node": ">=0.10.0" 1928 | } 1929 | }, 1930 | "node_modules/underscore": { 1931 | "version": "1.13.6", 1932 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", 1933 | "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", 1934 | "dev": true 1935 | }, 1936 | "node_modules/universalify": { 1937 | "version": "0.1.2", 1938 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1939 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1940 | "dev": true, 1941 | "engines": { 1942 | "node": ">= 4.0.0" 1943 | } 1944 | }, 1945 | "node_modules/uri-js": { 1946 | "version": "4.4.1", 1947 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1948 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1949 | "dev": true, 1950 | "dependencies": { 1951 | "punycode": "^2.1.0" 1952 | } 1953 | }, 1954 | "node_modules/uuid": { 1955 | "version": "3.3.3", 1956 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", 1957 | "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", 1958 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 1959 | "dev": true, 1960 | "bin": { 1961 | "uuid": "bin/uuid" 1962 | } 1963 | }, 1964 | "node_modules/validate-npm-package-license": { 1965 | "version": "3.0.4", 1966 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 1967 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 1968 | "dev": true, 1969 | "dependencies": { 1970 | "spdx-correct": "^3.0.0", 1971 | "spdx-expression-parse": "^3.0.0" 1972 | } 1973 | }, 1974 | "node_modules/verror": { 1975 | "version": "1.10.0", 1976 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1977 | "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", 1978 | "dev": true, 1979 | "engines": [ 1980 | "node >=0.6.0" 1981 | ], 1982 | "dependencies": { 1983 | "assert-plus": "^1.0.0", 1984 | "core-util-is": "1.0.2", 1985 | "extsprintf": "^1.2.0" 1986 | } 1987 | }, 1988 | "node_modules/which": { 1989 | "version": "1.3.1", 1990 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1991 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1992 | "dev": true, 1993 | "dependencies": { 1994 | "isexe": "^2.0.0" 1995 | }, 1996 | "bin": { 1997 | "which": "bin/which" 1998 | } 1999 | }, 2000 | "node_modules/which-module": { 2001 | "version": "2.0.0", 2002 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 2003 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 2004 | "dev": true 2005 | }, 2006 | "node_modules/wordwrap": { 2007 | "version": "1.0.0", 2008 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 2009 | "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", 2010 | "dev": true 2011 | }, 2012 | "node_modules/wrap-ansi": { 2013 | "version": "5.1.0", 2014 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 2015 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 2016 | "dev": true, 2017 | "dependencies": { 2018 | "ansi-styles": "^3.2.0", 2019 | "string-width": "^3.0.0", 2020 | "strip-ansi": "^5.0.0" 2021 | }, 2022 | "engines": { 2023 | "node": ">=6" 2024 | } 2025 | }, 2026 | "node_modules/wrappy": { 2027 | "version": "1.0.2", 2028 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2029 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2030 | "dev": true 2031 | }, 2032 | "node_modules/write-file-atomic": { 2033 | "version": "2.4.3", 2034 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", 2035 | "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", 2036 | "dev": true, 2037 | "dependencies": { 2038 | "graceful-fs": "^4.1.11", 2039 | "imurmurhash": "^0.1.4", 2040 | "signal-exit": "^3.0.2" 2041 | } 2042 | }, 2043 | "node_modules/xmlbuilder": { 2044 | "version": "11.0.1", 2045 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 2046 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", 2047 | "engines": { 2048 | "node": ">=4.0" 2049 | } 2050 | }, 2051 | "node_modules/y18n": { 2052 | "version": "4.0.3", 2053 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", 2054 | "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", 2055 | "dev": true 2056 | }, 2057 | "node_modules/yallist": { 2058 | "version": "2.1.2", 2059 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 2060 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 2061 | "dev": true 2062 | }, 2063 | "node_modules/yargs": { 2064 | "version": "13.3.0", 2065 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", 2066 | "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", 2067 | "dev": true, 2068 | "dependencies": { 2069 | "cliui": "^5.0.0", 2070 | "find-up": "^3.0.0", 2071 | "get-caller-file": "^2.0.1", 2072 | "require-directory": "^2.1.1", 2073 | "require-main-filename": "^2.0.0", 2074 | "set-blocking": "^2.0.0", 2075 | "string-width": "^3.0.0", 2076 | "which-module": "^2.0.0", 2077 | "y18n": "^4.0.0", 2078 | "yargs-parser": "^13.1.1" 2079 | } 2080 | }, 2081 | "node_modules/yargs-parser": { 2082 | "version": "13.1.2", 2083 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 2084 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 2085 | "dev": true, 2086 | "dependencies": { 2087 | "camelcase": "^5.0.0", 2088 | "decamelize": "^1.2.0" 2089 | } 2090 | }, 2091 | "node_modules/zap": { 2092 | "version": "0.2.9", 2093 | "resolved": "https://registry.npmjs.org/zap/-/zap-0.2.9.tgz", 2094 | "integrity": "sha1-3eS2+kL5xnC8yu/oCP42IrSFGMM=", 2095 | "dev": true, 2096 | "bin": { 2097 | "zap": "bin/zap" 2098 | } 2099 | } 2100 | } 2101 | } 2102 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xml2js", 3 | "description": "Simple XML to JavaScript object converter.", 4 | "keywords": [ 5 | "xml", 6 | "json" 7 | ], 8 | "homepage": "https://github.com/Leonidas-from-XIV/node-xml2js", 9 | "version": "0.6.2", 10 | "author": "Marek Kubica (https://xivilization.net)", 11 | "contributors": [ 12 | "maqr (https://github.com/maqr)", 13 | "Ben Weaver (http://benweaver.com/)", 14 | "Jae Kwon (https://github.com/jaekwon)", 15 | "Jim Robert", 16 | "Ștefan Rusu (http://www.saltwaterc.eu/)", 17 | "Carter Cole (http://cartercole.com/)", 18 | "Kurt Raschke (http://www.kurtraschke.com/)", 19 | "Contra (https://github.com/Contra)", 20 | "Marcelo Diniz (https://github.com/mdiniz)", 21 | "Michael Hart (https://github.com/mhart)", 22 | "Zachary Scott (http://zacharyscott.net/)", 23 | "Raoul Millais (https://github.com/raoulmillais)", 24 | "Salsita Software (http://www.salsitasoft.com/)", 25 | "Mike Schilling (http://www.emotive.com/)", 26 | "Jackson Tian (http://weibo.com/shyvo)", 27 | "Mikhail Zyatin (https://github.com/Sitin)", 28 | "Chris Tavares (https://github.com/christav)", 29 | "Frank Xu (http://f2e.us/)", 30 | "Guido D'Albore (http://www.bitstorm.it/)", 31 | "Jack Senechal (http://jacksenechal.com/)", 32 | "Matthias Hölzl (https://github.com/hoelzl)", 33 | "Camille Reynders (http://www.creynders.be/)", 34 | "Taylor Gautier (https://github.com/tsgautier)", 35 | "Todd Bryan (https://github.com/toddrbryan)", 36 | "Leore Avidar (http://leoreavidar.com/)", 37 | "Dave Aitken (http://www.actionshrimp.com/)", 38 | "Shaney Orrowe ", 39 | "Candle ", 40 | "Jess Telford (http://jes.st)", 41 | "Tom Hughes < (http://compton.nu/)", 42 | "Piotr Rochala (http://rocha.la/)", 43 | "Michael Avila (https://github.com/michaelavila)", 44 | "Ryan Gahl (https://github.com/ryedin)", 45 | "Eric Laberge (https://github.com/elaberge)", 46 | "Benjamin E. Coe (https://twitter.com/benjamincoe)", 47 | "Stephen Cresswell (https://github.com/cressie176)", 48 | "Pascal Ehlert (http://www.hacksrus.net/)", 49 | "Tom Spencer (http://fiznool.com/)", 50 | "Tristian Flanagan (https://github.com/tflanagan)", 51 | "Tim Johns (https://github.com/TimJohns)", 52 | "Bogdan Chadkin (https://github.com/TrySound)", 53 | "David Wood (http://codesleuth.co.uk/)", 54 | "Nicolas Maquet (https://github.com/nmaquet)", 55 | "Lovell Fuller (http://lovell.info/)", 56 | "d3adc0d3 (https://github.com/d3adc0d3)", 57 | "James Crosby (https://github.com/autopulated)" 58 | ], 59 | "main": "./lib/xml2js", 60 | "files": [ 61 | "lib" 62 | ], 63 | "directories": { 64 | "lib": "./lib" 65 | }, 66 | "scripts": { 67 | "build": "cake build", 68 | "test": "zap", 69 | "coverage": "nyc npm test && nyc report", 70 | "coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls", 71 | "doc": "cake doc" 72 | }, 73 | "repository": { 74 | "type": "git", 75 | "url": "https://github.com/Leonidas-from-XIV/node-xml2js.git" 76 | }, 77 | "dependencies": { 78 | "sax": ">=0.6.0", 79 | "xmlbuilder": "~11.0.0" 80 | }, 81 | "devDependencies": { 82 | "coffeescript": ">=1.10.0 <2", 83 | "coveralls": "^3.0.1", 84 | "diff": ">=1.0.8", 85 | "docco": ">=0.6.2", 86 | "nyc": ">=2.2.1", 87 | "zap": ">=0.2.9 <1" 88 | }, 89 | "engines": { 90 | "node": ">=4.0.0" 91 | }, 92 | "license": "MIT" 93 | } 94 | -------------------------------------------------------------------------------- /src/bom.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | exports.stripBOM = (str) -> 4 | if str[0] == '\uFEFF' 5 | str.substring(1) 6 | else 7 | str 8 | -------------------------------------------------------------------------------- /src/builder.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | builder = require 'xmlbuilder' 4 | defaults = require('./defaults').defaults 5 | 6 | requiresCDATA = (entry) -> 7 | return typeof entry is "string" && (entry.indexOf('&') >= 0 || entry.indexOf('>') >= 0 || entry.indexOf('<') >= 0) 8 | 9 | # Note that we do this manually instead of using xmlbuilder's `.dat` method 10 | # since it does not support escaping the CDATA close entity (throws an error if 11 | # it exists, and if it's pre-escaped). 12 | wrapCDATA = (entry) -> 13 | return "" 14 | 15 | escapeCDATA = (entry) -> 16 | # Split the CDATA section in two; 17 | # The first contains the ']]' 18 | # The second contains the '>' 19 | # When later parsed, it will be put back together as ']]>' 20 | return entry.replace ']]>', ']]]]>' 21 | 22 | class exports.Builder 23 | constructor: (opts) -> 24 | # copy this versions default options 25 | @options = {} 26 | @options[key] = value for own key, value of defaults["0.2"] 27 | # overwrite them with the specified options, if any 28 | @options[key] = value for own key, value of opts 29 | 30 | buildObject: (rootObj) -> 31 | attrkey = @options.attrkey 32 | charkey = @options.charkey 33 | 34 | # If there is a sane-looking first element to use as the root, 35 | # and the user hasn't specified a non-default rootName, 36 | if ( Object.keys(rootObj).length is 1 ) and ( @options.rootName == defaults['0.2'].rootName ) 37 | # we'll take the first element as the root element 38 | rootName = Object.keys(rootObj)[0] 39 | rootObj = rootObj[rootName] 40 | else 41 | # otherwise we'll use whatever they've set, or the default 42 | rootName = @options.rootName 43 | 44 | render = (element, obj) => 45 | if typeof obj isnt 'object' 46 | # single element, just append it as text 47 | if @options.cdata && requiresCDATA obj 48 | element.raw wrapCDATA obj 49 | else 50 | element.txt obj 51 | else if Array.isArray obj 52 | # fix issue #119 53 | for own index, child of obj 54 | for key, entry of child 55 | element = render(element.ele(key), entry).up() 56 | else 57 | for own key, child of obj 58 | # Case #1 Attribute 59 | if key is attrkey 60 | if typeof child is "object" 61 | # Inserts tag attributes 62 | for attr, value of child 63 | element = element.att(attr, value) 64 | 65 | # Case #2 Char data (CDATA, etc.) 66 | else if key is charkey 67 | if @options.cdata && requiresCDATA child 68 | element = element.raw wrapCDATA child 69 | else 70 | element = element.txt child 71 | 72 | # Case #3 Array data 73 | else if Array.isArray child 74 | for own index, entry of child 75 | if typeof entry is 'string' 76 | if @options.cdata && requiresCDATA entry 77 | element = element.ele(key).raw(wrapCDATA entry).up() 78 | else 79 | element = element.ele(key, entry).up() 80 | else 81 | element = render(element.ele(key), entry).up() 82 | 83 | # Case #4 Objects 84 | else if typeof child is "object" 85 | element = render(element.ele(key), child).up() 86 | 87 | # Case #5 String and remaining types 88 | else 89 | if typeof child is 'string' && @options.cdata && requiresCDATA child 90 | element = element.ele(key).raw(wrapCDATA child).up() 91 | else 92 | if not child? 93 | child = '' 94 | element = element.ele(key, child.toString()).up() 95 | 96 | element 97 | 98 | rootElement = builder.create(rootName, @options.xmldec, @options.doctype, 99 | headless: @options.headless 100 | allowSurrogateChars: @options.allowSurrogateChars) 101 | 102 | render(rootElement, rootObj).end(@options.renderOpts) 103 | -------------------------------------------------------------------------------- /src/defaults.coffee: -------------------------------------------------------------------------------- 1 | exports.defaults = { 2 | "0.1": 3 | explicitCharkey: false 4 | trim: true 5 | # normalize implicates trimming, just so you know 6 | normalize: true 7 | # normalize tag names to lower case 8 | normalizeTags: false 9 | # set default attribute object key 10 | attrkey: "@" 11 | # set default char object key 12 | charkey: "#" 13 | # always put child nodes in an array 14 | explicitArray: false 15 | # ignore all attributes regardless 16 | ignoreAttrs: false 17 | # merge attributes and child elements onto parent object. this may 18 | # cause collisions. 19 | mergeAttrs: false 20 | explicitRoot: false 21 | validator: null 22 | xmlns : false 23 | # fold children elements into dedicated property (works only in 0.2) 24 | explicitChildren: false 25 | childkey: '@@' 26 | charsAsChildren: false 27 | # include white-space only text nodes 28 | includeWhiteChars: false 29 | # callbacks are async? not in 0.1 mode 30 | async: false 31 | strict: true 32 | attrNameProcessors: null 33 | attrValueProcessors: null 34 | tagNameProcessors: null 35 | valueProcessors: null 36 | emptyTag: '' 37 | 38 | "0.2": 39 | explicitCharkey: false 40 | trim: false 41 | normalize: false 42 | normalizeTags: false 43 | attrkey: "$" 44 | charkey: "_" 45 | explicitArray: true 46 | ignoreAttrs: false 47 | mergeAttrs: false 48 | explicitRoot: true 49 | validator: null 50 | xmlns : false 51 | explicitChildren: false 52 | preserveChildrenOrder: false 53 | childkey: '$$' 54 | charsAsChildren: false 55 | # include white-space only text nodes 56 | includeWhiteChars: false 57 | # not async in 0.2 mode either 58 | async: false 59 | strict: true 60 | attrNameProcessors: null 61 | attrValueProcessors: null 62 | tagNameProcessors: null 63 | valueProcessors: null 64 | # xml building options 65 | rootName: 'root' 66 | xmldec: {'version': '1.0', 'encoding': 'UTF-8', 'standalone': true} 67 | doctype: null 68 | renderOpts: { 'pretty': true, 'indent': ' ', 'newline': '\n' } 69 | headless: false 70 | chunkSize: 10000 71 | emptyTag: '' 72 | cdata: false 73 | } 74 | -------------------------------------------------------------------------------- /src/parser.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | sax = require 'sax' 4 | events = require 'events' 5 | bom = require './bom' 6 | processors = require './processors' 7 | setImmediate = require('timers').setImmediate 8 | defaults = require('./defaults').defaults 9 | 10 | # Underscore has a nice function for this, but we try to go without dependencies 11 | isEmpty = (thing) -> 12 | return typeof thing is "object" && thing? && Object.keys(thing).length is 0 13 | 14 | processItem = (processors, item, key) -> 15 | item = process(item, key) for process in processors 16 | return item 17 | 18 | defineProperty = (obj, key, value) -> 19 | # make sure the descriptor hasn't been prototype polluted 20 | descriptor = Object.create null 21 | descriptor.value = value 22 | descriptor.writable = true 23 | descriptor.enumerable = true 24 | descriptor.configurable = true 25 | Object.defineProperty obj, key, descriptor 26 | 27 | class exports.Parser extends events 28 | constructor: (opts) -> 29 | # if this was called without 'new', create an instance with new and return 30 | return new exports.Parser opts unless @ instanceof exports.Parser 31 | # copy this versions default options 32 | @options = {} 33 | @options[key] = value for own key, value of defaults["0.2"] 34 | # overwrite them with the specified options, if any 35 | @options[key] = value for own key, value of opts 36 | # define the key used for namespaces 37 | if @options.xmlns 38 | @options.xmlnskey = @options.attrkey + "ns" 39 | if @options.normalizeTags 40 | if ! @options.tagNameProcessors 41 | @options.tagNameProcessors = [] 42 | @options.tagNameProcessors.unshift processors.normalize 43 | 44 | @reset() 45 | 46 | processAsync: => 47 | try 48 | if @remaining.length <= @options.chunkSize 49 | chunk = @remaining 50 | @remaining = '' 51 | @saxParser = @saxParser.write chunk 52 | @saxParser.close() 53 | else 54 | chunk = @remaining.substr 0, @options.chunkSize 55 | @remaining = @remaining.substr @options.chunkSize, @remaining.length 56 | @saxParser = @saxParser.write chunk 57 | setImmediate @processAsync 58 | catch err 59 | if ! @saxParser.errThrown 60 | @saxParser.errThrown = true 61 | @emit err 62 | 63 | assignOrPush: (obj, key, newValue) => 64 | if key not of obj 65 | if not @options.explicitArray 66 | defineProperty obj, key, newValue 67 | else 68 | defineProperty obj, key, [newValue] 69 | else 70 | unless obj[key] instanceof Array 71 | defineProperty obj, key, [obj[key]] 72 | obj[key].push newValue 73 | 74 | reset: => 75 | # remove all previous listeners for events, to prevent event listener 76 | # accumulation 77 | @removeAllListeners() 78 | # make the SAX parser. tried trim and normalize, but they are not 79 | # very helpful 80 | @saxParser = sax.parser @options.strict, { 81 | trim: false, 82 | normalize: false, 83 | xmlns: @options.xmlns 84 | } 85 | 86 | # emit one error event if the sax parser fails. this is mostly a hack, but 87 | # the sax parser isn't state of the art either. 88 | @saxParser.errThrown = false 89 | @saxParser.onerror = (error) => 90 | @saxParser.resume() 91 | if ! @saxParser.errThrown 92 | @saxParser.errThrown = true 93 | @emit "error", error 94 | 95 | @saxParser.onend = () => 96 | if ! @saxParser.ended 97 | @saxParser.ended = true 98 | @emit "end", @resultObject 99 | 100 | # another hack to avoid throwing exceptions when the parsing has ended 101 | # but the user-supplied callback throws an error 102 | @saxParser.ended = false 103 | 104 | # always use the '#' key, even if there are no subkeys 105 | # setting this property by and is deprecated, yet still supported. 106 | # better pass it as explicitCharkey option to the constructor 107 | @EXPLICIT_CHARKEY = @options.explicitCharkey 108 | @resultObject = null 109 | stack = [] 110 | # aliases, so we don't have to type so much 111 | attrkey = @options.attrkey 112 | charkey = @options.charkey 113 | 114 | @saxParser.onopentag = (node) => 115 | obj = {} 116 | obj[charkey] = "" 117 | unless @options.ignoreAttrs 118 | for own key of node.attributes 119 | if attrkey not of obj and not @options.mergeAttrs 120 | obj[attrkey] = {} 121 | newValue = if @options.attrValueProcessors then processItem(@options.attrValueProcessors, node.attributes[key], key) else node.attributes[key] 122 | processedKey = if @options.attrNameProcessors then processItem(@options.attrNameProcessors, key) else key 123 | if @options.mergeAttrs 124 | @assignOrPush obj, processedKey, newValue 125 | else 126 | defineProperty obj[attrkey], processedKey, newValue 127 | 128 | # need a place to store the node name 129 | obj["#name"] = if @options.tagNameProcessors then processItem(@options.tagNameProcessors, node.name) else node.name 130 | if (@options.xmlns) 131 | obj[@options.xmlnskey] = {uri: node.uri, local: node.local} 132 | stack.push obj 133 | 134 | @saxParser.onclosetag = => 135 | obj = stack.pop() 136 | nodeName = obj["#name"] 137 | delete obj["#name"] if not @options.explicitChildren or not @options.preserveChildrenOrder 138 | 139 | if obj.cdata == true 140 | cdata = obj.cdata 141 | delete obj.cdata 142 | 143 | s = stack[stack.length - 1] 144 | # remove the '#' key altogether if it's blank 145 | if obj[charkey].match(/^\s*$/) and not cdata 146 | emptyStr = obj[charkey] 147 | delete obj[charkey] 148 | else 149 | obj[charkey] = obj[charkey].trim() if @options.trim 150 | obj[charkey] = obj[charkey].replace(/\s{2,}/g, " ").trim() if @options.normalize 151 | obj[charkey] = if @options.valueProcessors then processItem @options.valueProcessors, obj[charkey], nodeName else obj[charkey] 152 | # also do away with '#' key altogether, if there's no subkeys 153 | # unless EXPLICIT_CHARKEY is set 154 | if Object.keys(obj).length == 1 and charkey of obj and not @EXPLICIT_CHARKEY 155 | obj = obj[charkey] 156 | 157 | if (isEmpty obj) 158 | if typeof @options.emptyTag == 'function' 159 | obj = @options.emptyTag() 160 | else 161 | obj = if @options.emptyTag != '' then @options.emptyTag else emptyStr 162 | 163 | if @options.validator? 164 | xpath = "/" + (node["#name"] for node in stack).concat(nodeName).join("/") 165 | # Wrap try/catch with an inner function to allow V8 to optimise the containing function 166 | # See https://github.com/Leonidas-from-XIV/node-xml2js/pull/369 167 | do => 168 | try 169 | obj = @options.validator(xpath, s and s[nodeName], obj) 170 | catch err 171 | @emit "error", err 172 | 173 | # put children into property and unfold chars if necessary 174 | if @options.explicitChildren and not @options.mergeAttrs and typeof obj is 'object' 175 | if not @options.preserveChildrenOrder 176 | node = {} 177 | # separate attributes 178 | if @options.attrkey of obj 179 | node[@options.attrkey] = obj[@options.attrkey] 180 | delete obj[@options.attrkey] 181 | # separate char data 182 | if not @options.charsAsChildren and @options.charkey of obj 183 | node[@options.charkey] = obj[@options.charkey] 184 | delete obj[@options.charkey] 185 | 186 | if Object.getOwnPropertyNames(obj).length > 0 187 | node[@options.childkey] = obj 188 | 189 | obj = node 190 | else if s 191 | # append current node onto parent's array 192 | s[@options.childkey] = s[@options.childkey] or [] 193 | # push a clone so that the node in the children array can receive the #name property while the original obj can do without it 194 | objClone = {} 195 | for own key of obj 196 | defineProperty objClone, key, obj[key] 197 | s[@options.childkey].push objClone 198 | delete obj["#name"] 199 | # re-check whether we can collapse the node now to just the charkey value 200 | if Object.keys(obj).length == 1 and charkey of obj and not @EXPLICIT_CHARKEY 201 | obj = obj[charkey] 202 | 203 | # check whether we closed all the open tags 204 | if stack.length > 0 205 | @assignOrPush s, nodeName, obj 206 | else 207 | # if explicitRoot was specified, wrap stuff in the root tag name 208 | if @options.explicitRoot 209 | # avoid circular references 210 | old = obj 211 | obj = {} 212 | defineProperty obj, nodeName, old 213 | 214 | @resultObject = obj 215 | # parsing has ended, mark that so we won't throw exceptions from 216 | # here anymore 217 | @saxParser.ended = true 218 | @emit "end", @resultObject 219 | 220 | ontext = (text) => 221 | s = stack[stack.length - 1] 222 | if s 223 | s[charkey] += text 224 | 225 | if @options.explicitChildren and @options.preserveChildrenOrder and @options.charsAsChildren and (@options.includeWhiteChars or text.replace(/\\n/g, '').trim() isnt '') 226 | s[@options.childkey] = s[@options.childkey] or [] 227 | charChild = 228 | '#name': '__text__' 229 | charChild[charkey] = text 230 | charChild[charkey] = charChild[charkey].replace(/\s{2,}/g, " ").trim() if @options.normalize 231 | s[@options.childkey].push charChild 232 | 233 | s 234 | 235 | @saxParser.ontext = ontext 236 | @saxParser.oncdata = (text) => 237 | s = ontext text 238 | if s 239 | s.cdata = true 240 | 241 | parseString: (str, cb) => 242 | if cb? and typeof cb is "function" 243 | @on "end", (result) -> 244 | @reset() 245 | cb null, result 246 | @on "error", (err) -> 247 | @reset() 248 | cb err 249 | 250 | try 251 | str = str.toString() 252 | if str.trim() is '' 253 | @emit "end", null 254 | return true 255 | 256 | str = bom.stripBOM str 257 | if @options.async 258 | @remaining = str 259 | setImmediate @processAsync 260 | return @saxParser 261 | @saxParser.write(str).close() 262 | catch err 263 | unless @saxParser.errThrown or @saxParser.ended 264 | @emit 'error', err 265 | @saxParser.errThrown = true 266 | else if @saxParser.ended 267 | throw err 268 | 269 | parseStringPromise: (str) => 270 | new Promise (resolve, reject) => 271 | @parseString str, (err, value) => 272 | if err 273 | reject err 274 | else 275 | resolve value 276 | 277 | exports.parseString = (str, a, b) -> 278 | # let's determine what we got as arguments 279 | if b? 280 | if typeof b == 'function' 281 | cb = b 282 | if typeof a == 'object' 283 | options = a 284 | else 285 | # well, b is not set, so a has to be a callback 286 | if typeof a == 'function' 287 | cb = a 288 | # and options should be empty - default 289 | options = {} 290 | 291 | # the rest is super-easy 292 | parser = new exports.Parser options 293 | parser.parseString str, cb 294 | 295 | exports.parseStringPromise = (str, a) -> 296 | if typeof a == 'object' 297 | options = a 298 | 299 | parser = new exports.Parser options 300 | parser.parseStringPromise str 301 | -------------------------------------------------------------------------------- /src/processors.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | # matches all xml prefixes, except for `xmlns:` 4 | prefixMatch = new RegExp /(?!xmlns)^.*:/ 5 | 6 | exports.normalize = (str) -> 7 | return str.toLowerCase() 8 | 9 | exports.firstCharLowerCase = (str) -> 10 | return str.charAt(0).toLowerCase() + str.slice(1) 11 | 12 | exports.stripPrefix = (str) -> 13 | return str.replace prefixMatch, '' 14 | 15 | exports.parseNumbers = (str) -> 16 | if !isNaN str 17 | str = if str % 1 == 0 then parseInt str, 10 else parseFloat str 18 | return str 19 | 20 | exports.parseBooleans = (str) -> 21 | if /^(?:true|false)$/i.test(str) 22 | str = str.toLowerCase() == 'true' 23 | return str 24 | -------------------------------------------------------------------------------- /src/xml2js.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | defaults = require './defaults' 4 | builder = require './builder' 5 | parser = require './parser' 6 | processors = require './processors' 7 | 8 | exports.defaults = defaults.defaults 9 | 10 | exports.processors = processors 11 | 12 | class exports.ValidationError extends Error 13 | constructor: (message) -> 14 | @message = message 15 | 16 | exports.Builder = builder.Builder 17 | 18 | exports.Parser = parser.Parser 19 | 20 | exports.parseString = parser.parseString 21 | exports.parseStringPromise = parser.parseStringPromise 22 | -------------------------------------------------------------------------------- /test/bom.test.coffee: -------------------------------------------------------------------------------- 1 | xml2js = require '../lib/xml2js' 2 | assert = require 'assert' 3 | equ = assert.equal 4 | 5 | module.exports = 6 | 'test decoded BOM': (test) -> 7 | demo = '\uFEFFbar' 8 | xml2js.parseString demo, (err, res) -> 9 | equ err, undefined 10 | equ res.xml.foo[0], 'bar' 11 | test.done() 12 | -------------------------------------------------------------------------------- /test/builder.test.coffee: -------------------------------------------------------------------------------- 1 | # use zap to run tests, it also detects CoffeeScript files 2 | xml2js = require '../lib/xml2js' 3 | assert = require 'assert' 4 | fs = require 'fs' 5 | path = require 'path' 6 | diff = require 'diff' 7 | 8 | # fileName = path.join __dirname, '/fixtures/sample.xml' 9 | 10 | # shortcut, because it is quite verbose 11 | equ = assert.equal 12 | 13 | # equality test with diff output 14 | diffeq = (expected, actual) -> 15 | diffless = "Index: test\n===================================================================\n--- test\texpected\n+++ test\tactual\n" 16 | patch = diff.createPatch('test', expected.trim(), actual.trim(), 'expected', 'actual') 17 | throw patch unless patch is diffless 18 | 19 | module.exports = 20 | 'test building basic XML structure': (test) -> 21 | expected = '' 22 | obj = {"xml":{"Label":[""],"MsgId":["5850440872586764820"]}} 23 | builder = new xml2js.Builder renderOpts: pretty: false 24 | actual = builder.buildObject obj 25 | diffeq expected, actual 26 | test.finish() 27 | 28 | 'test setting XML declaration': (test) -> 29 | expected = '' 30 | opts = 31 | renderOpts: pretty: false 32 | xmldec: 'version': '1.2', 'encoding': 'WTF-8', 'standalone': false 33 | builder = new xml2js.Builder opts 34 | actual = builder.buildObject {} 35 | diffeq expected, actual 36 | test.finish() 37 | 38 | 'test pretty by default': (test) -> 39 | expected = """ 40 | 41 | 42 | 5850440872586764820 43 | 44 | 45 | """ 46 | builder = new xml2js.Builder() 47 | obj = {"xml":{"MsgId":["5850440872586764820"]}} 48 | actual = builder.buildObject obj 49 | diffeq expected, actual 50 | test.finish() 51 | 52 | 'test setting indentation': (test) -> 53 | expected = """ 54 | 55 | 56 | 5850440872586764820 57 | 58 | 59 | """ 60 | opts = renderOpts: pretty: true, indent: ' ' 61 | builder = new xml2js.Builder opts 62 | obj = {"xml":{"MsgId":["5850440872586764820"]}} 63 | actual = builder.buildObject obj 64 | diffeq expected, actual 65 | test.finish() 66 | 67 | 'test headless option': (test) -> 68 | expected = """ 69 | 70 | 5850440872586764820 71 | 72 | 73 | """ 74 | opts = 75 | renderOpts: pretty: true, indent: ' ' 76 | headless: true 77 | builder = new xml2js.Builder opts 78 | obj = {"xml":{"MsgId":["5850440872586764820"]}} 79 | actual = builder.buildObject obj 80 | diffeq expected, actual 81 | test.finish() 82 | 83 | 'test allowSurrogateChars option': (test) -> 84 | expected = """ 85 | 86 | 87 | \uD83D\uDC33 88 | 89 | 90 | """ 91 | opts = 92 | renderOpts: pretty: true, indent: ' ' 93 | allowSurrogateChars: true 94 | builder = new xml2js.Builder opts 95 | obj = {"xml":{"MsgId":["\uD83D\uDC33"]}} 96 | actual = builder.buildObject obj 97 | diffeq expected, actual 98 | test.finish() 99 | 100 | 'test explicit rootName is always used: 1. when there is only one element': (test) -> 101 | expected = '5850440872586764820' 102 | opts = renderOpts: {pretty: false}, rootName: 'FOO' 103 | builder = new xml2js.Builder opts 104 | obj = {"MsgId":["5850440872586764820"]} 105 | actual = builder.buildObject obj 106 | diffeq expected, actual 107 | test.finish() 108 | 109 | 'test explicit rootName is always used: 2. when there are multiple elements': (test) -> 110 | expected = '5850440872586764820' 111 | opts = renderOpts: {pretty: false}, rootName: 'FOO' 112 | builder = new xml2js.Builder opts 113 | obj = {"MsgId":["5850440872586764820"]} 114 | actual = builder.buildObject obj 115 | diffeq expected, actual 116 | test.finish() 117 | 118 | 'test default rootName is used when there is more than one element in the hash': (test) -> 119 | expected = '5850440872586764820bar' 120 | opts = renderOpts: pretty: false 121 | builder = new xml2js.Builder opts 122 | obj = {"MsgId":["5850440872586764820"],"foo":"bar"} 123 | actual = builder.buildObject obj 124 | diffeq expected, actual 125 | test.finish() 126 | 127 | 'test when there is only one first-level element in the hash, that is used as root': (test) -> 128 | expected = '5850440872586764820bar' 129 | opts = renderOpts: pretty: false 130 | builder = new xml2js.Builder opts 131 | obj = {"first":{"MsgId":["5850440872586764820"],"foo":"bar"}} 132 | actual = builder.buildObject obj 133 | diffeq expected, actual 134 | test.finish() 135 | 136 | 'test parser -> builder roundtrip': (test) -> 137 | fileName = path.join __dirname, '/fixtures/build_sample.xml' 138 | fs.readFile fileName, (err, xmlData) -> 139 | xmlExpected = xmlData.toString() 140 | xml2js.parseString xmlData, {'trim': true}, (err, obj) -> 141 | equ err, null 142 | builder = new xml2js.Builder({}) 143 | xmlActual = builder.buildObject obj 144 | diffeq xmlExpected, xmlActual 145 | test.finish() 146 | 147 | 'test building obj with undefined value' : (test) -> 148 | obj = { node: 'string', anothernode: undefined } 149 | builder = new xml2js.Builder renderOpts: { pretty: false } 150 | actual = builder.buildObject(obj); 151 | expected = 'string' 152 | equ actual, expected 153 | test.finish(); 154 | 155 | 'test building obj with null value' : (test) -> 156 | obj = { node: 'string', anothernode: null } 157 | builder = new xml2js.Builder renderOpts: { pretty: false } 158 | actual = builder.buildObject(obj); 159 | expected = 'string' 160 | equ actual, expected 161 | test.finish(); 162 | 163 | 'test escapes escaped characters': (test) -> 164 | expected = """ 165 | 166 | 167 | &amp;&lt;&gt; 168 | 169 | 170 | """ 171 | builder = new xml2js.Builder 172 | obj = {"xml":{"MsgId":["&<>"]}} 173 | actual = builder.buildObject obj 174 | diffeq expected, actual 175 | test.finish() 176 | 177 | 'test cdata text nodes': (test) -> 178 | expected = """ 179 | 180 | 181 | 182 | 183 | 184 | """ 185 | opts = cdata: true 186 | builder = new xml2js.Builder opts 187 | obj = {"xml":{"MsgId":["& <<"]}} 188 | actual = builder.buildObject obj 189 | diffeq expected, actual 190 | test.finish() 191 | 192 | 'test cdata text nodes with escaped end sequence': (test) -> 193 | expected = """ 194 | 195 | 196 | ]]> 197 | 198 | 199 | """ 200 | opts = cdata: true 201 | builder = new xml2js.Builder opts 202 | obj = {"xml":{"MsgId":["& <<]]>"]}} 203 | actual = builder.buildObject obj 204 | diffeq expected, actual 205 | test.finish() 206 | 207 | 'test uses cdata only for chars &, <, >': (test) -> 208 | expected = """ 209 | 210 | 211 | 212 | Hello 213 | 214 | 215 | """ 216 | opts = cdata: true 217 | builder = new xml2js.Builder opts 218 | obj = {"xml":{"MsgId":["& <<"],"Message":["Hello"]}} 219 | actual = builder.buildObject obj 220 | diffeq expected, actual 221 | test.finish() 222 | 223 | 'test uses cdata for string values of objects': (test) -> 224 | expected = """ 225 | 226 | 227 | 228 | 229 | 230 | """ 231 | opts = cdata: true 232 | builder = new xml2js.Builder opts 233 | obj = {"xml":{"MsgId":"& <<"}} 234 | actual = builder.buildObject obj 235 | diffeq expected, actual 236 | test.finish() 237 | 238 | 'test does not error on non string values when checking for cdata': (test) -> 239 | expected = """ 240 | 241 | 242 | 10 243 | 244 | 245 | """ 246 | opts = cdata: true 247 | builder = new xml2js.Builder opts 248 | obj = {"xml":{"MsgId":10}} 249 | actual = builder.buildObject obj 250 | diffeq expected, actual 251 | test.finish() 252 | 253 | 'test does not error on array values when checking for cdata': (test) -> 254 | expected = """ 255 | 256 | 257 | 10 258 | 12 259 | 260 | 261 | """ 262 | opts = cdata: true 263 | builder = new xml2js.Builder opts 264 | obj = {"xml":{"MsgId":[10, 12]}} 265 | actual = builder.buildObject obj 266 | diffeq expected, actual 267 | test.finish() 268 | 269 | 'test building obj with array': (test) -> 270 | expected = """ 271 | 272 | 273 | 10 274 | 12 275 | 276 | 277 | """ 278 | opts = cdata: true 279 | builder = new xml2js.Builder opts 280 | obj = [{"MsgId": 10}, {"MsgId2": 12}] 281 | actual = builder.buildObject obj 282 | diffeq expected, actual 283 | test.finish() 284 | -------------------------------------------------------------------------------- /test/fixtures/build_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Character data here! 4 | 5 | 6 | 7 | 8 | This is 9 | character 10 | data! 11 | Foo(1) 12 | Foo(2) 13 | Foo(3) 14 | Foo(4) 15 | 16 | Qux. 17 | Quux. 18 | 19 | 20 | 21 | Baz. 22 | 23 | 24 | Foo. 25 | Bar. 26 | 27 | 28 | 29 | 30 | 31 | 32 | something 33 | something else 34 | something third 35 | 36 | 37 | 1 38 | 4 39 | 2 40 | 5 41 | 3 42 | 6 43 | 44 | 45 | 46 | 47 | 48 | 49 | Bar. 50 | 51 | 42 52 | 43 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /test/fixtures/sample.xml: -------------------------------------------------------------------------------- 1 | 2 | Character data here! 3 | 4 | 5 | 6 | 7 | 8 | Line One 9 | Line Two 10 | 11 | 12 | 13 | This Foo(1) is 14 | Foo(2) 15 | character 16 | Foo(3) 17 | data! 18 | Foo(4) 19 | 20 | Qux. 21 | Quux. 22 | Single 23 | 24 | 25 | Baz. 26 | Foo.Bar. 27 | 28 | 29 | 30 | something 31 | something else 32 | something third 33 | 34 | 35 | 1 36 | 2 37 | 3 38 | 4 39 | 5 40 | 6 41 | 42 | 43 | 44 | 45 | Bar. 46 | 47 | 42 48 | 43 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | some value 57 | this is text with markup like this in the middle 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /test/parser.test.coffee: -------------------------------------------------------------------------------- 1 | # use zap to run tests, it also detects CoffeeScript files 2 | xml2js = require '../lib/xml2js' 3 | fs = require 'fs' 4 | util = require 'util' 5 | assert = require 'assert' 6 | path = require 'path' 7 | os = require 'os' 8 | 9 | fileName = path.join __dirname, '/fixtures/sample.xml' 10 | 11 | readFilePromise = (fileName) -> 12 | new Promise (resolve, reject) => 13 | fs.readFile fileName, (err, value) => 14 | if err 15 | reject err 16 | else 17 | resolve value 18 | 19 | skeleton = (options, checks) -> 20 | (test) -> 21 | xmlString = options?.__xmlString 22 | delete options?.__xmlString 23 | x2js = new xml2js.Parser options 24 | x2js.addListener 'end', (r) -> 25 | checks r 26 | test.finish() 27 | if not xmlString 28 | fs.readFile fileName, 'utf8', (err, data) -> 29 | data = data.split(os.EOL).join('\n') 30 | x2js.parseString data 31 | else 32 | x2js.parseString xmlString 33 | 34 | nameToUpperCase = (name) -> 35 | return name.toUpperCase() 36 | 37 | nameCutoff = (name) -> 38 | return name.substr(0, 4) 39 | 40 | replaceValueByName = (value, name) -> 41 | return name 42 | 43 | ### 44 | The `validator` function validates the value at the XPath. It also transforms the value 45 | if necessary to conform to the schema or other validation information being used. If there 46 | is an existing value at this path it is supplied in `currentValue` (e.g. this is the second or 47 | later item in an array). 48 | If the validation fails it should throw a `ValidationError`. 49 | ### 50 | validator = (xpath, currentValue, newValue) -> 51 | if xpath == '/sample/validatortest/numbertest' 52 | return Number(newValue) 53 | else if xpath in ['/sample/arraytest', '/sample/validatortest/emptyarray', '/sample/validatortest/oneitemarray'] 54 | if not newValue or not ('item' of newValue) 55 | return {'item': []} 56 | else if xpath in ['/sample/arraytest/item', '/sample/validatortest/emptyarray/item', '/sample/validatortest/oneitemarray/item'] 57 | if not currentValue 58 | return newValue 59 | else if xpath == '/validationerror' 60 | throw new xml2js.ValidationError("Validation error!") 61 | return newValue 62 | 63 | # shortcut, because it is quite verbose 64 | equ = assert.strictEqual 65 | 66 | module.exports = 67 | 'test parse with defaults': skeleton(undefined, (r) -> 68 | console.log 'Result object: ' + util.inspect r, false, 10 69 | equ r.sample.chartest[0].$.desc, 'Test for CHARs' 70 | equ r.sample.chartest[0]._, 'Character data here!' 71 | equ r.sample.cdatatest[0].$.desc, 'Test for CDATA' 72 | equ r.sample.cdatatest[0].$.misc, 'true' 73 | equ r.sample.cdatatest[0]._, 'CDATA here!' 74 | equ r.sample.nochartest[0].$.desc, 'No data' 75 | equ r.sample.nochartest[0].$.misc, 'false' 76 | equ r.sample.listtest[0].item[0]._, '\n This is\n \n character\n \n data!\n \n ' 77 | equ r.sample.listtest[0].item[0].subitem[0], 'Foo(1)' 78 | equ r.sample.listtest[0].item[0].subitem[1], 'Foo(2)' 79 | equ r.sample.listtest[0].item[0].subitem[2], 'Foo(3)' 80 | equ r.sample.listtest[0].item[0].subitem[3], 'Foo(4)' 81 | equ r.sample.listtest[0].item[1], 'Qux.' 82 | equ r.sample.listtest[0].item[2], 'Quux.' 83 | # determine number of items in object 84 | equ Object.keys(r.sample.tagcasetest[0]).length, 3) 85 | 86 | 'test parse with empty objects and functions': skeleton({emptyTag: ()=> ({})}, (r)-> 87 | console.log 'Result object: ' + util.inspect r, false, 10 88 | bool = r.sample.emptytestanother[0] is r.sample.emptytest[0] 89 | equ bool, false) 90 | 91 | 'test parse with explicitCharkey': skeleton(explicitCharkey: true, (r) -> 92 | console.log 'Result object: ' + util.inspect r, false, 10 93 | equ r.sample.chartest[0].$.desc, 'Test for CHARs' 94 | equ r.sample.chartest[0]._, 'Character data here!' 95 | equ r.sample.cdatatest[0].$.desc, 'Test for CDATA' 96 | equ r.sample.cdatatest[0].$.misc, 'true' 97 | equ r.sample.cdatatest[0]._, 'CDATA here!' 98 | equ r.sample.nochartest[0].$.desc, 'No data' 99 | equ r.sample.nochartest[0].$.misc, 'false' 100 | equ r.sample.listtest[0].item[0]._, '\n This is\n \n character\n \n data!\n \n ' 101 | equ r.sample.listtest[0].item[0].subitem[0]._, 'Foo(1)' 102 | equ r.sample.listtest[0].item[0].subitem[1]._, 'Foo(2)' 103 | equ r.sample.listtest[0].item[0].subitem[2]._, 'Foo(3)' 104 | equ r.sample.listtest[0].item[0].subitem[3]._, 'Foo(4)' 105 | equ r.sample.listtest[0].item[1]._, 'Qux.' 106 | equ r.sample.listtest[0].item[2]._, 'Quux.') 107 | 108 | 'test parse with mergeAttrs': skeleton(mergeAttrs: true, (r) -> 109 | console.log 'Result object: ' + util.inspect r, false, 10 110 | equ r.sample.chartest[0].desc[0], 'Test for CHARs' 111 | equ r.sample.chartest[0]._, 'Character data here!' 112 | equ r.sample.cdatatest[0].desc[0], 'Test for CDATA' 113 | equ r.sample.cdatatest[0].misc[0], 'true' 114 | equ r.sample.cdatatest[0]._, 'CDATA here!' 115 | equ r.sample.nochartest[0].desc[0], 'No data' 116 | equ r.sample.nochartest[0].misc[0], 'false' 117 | equ r.sample.listtest[0].item[0].subitem[0], 'Foo(1)' 118 | equ r.sample.listtest[0].item[0].subitem[1], 'Foo(2)' 119 | equ r.sample.listtest[0].item[0].subitem[2], 'Foo(3)' 120 | equ r.sample.listtest[0].item[0].subitem[3], 'Foo(4)' 121 | equ r.sample.listtest[0].item[1], 'Qux.' 122 | equ r.sample.listtest[0].item[2], 'Quux.' 123 | equ r.sample.listtest[0].single[0], 'Single' 124 | equ r.sample.listtest[0].attr[0], 'Attribute') 125 | 126 | 'test parse with mergeAttrs and not explicitArray': skeleton(mergeAttrs: true, explicitArray: false, (r) -> 127 | console.log 'Result object: ' + util.inspect r, false, 10 128 | equ r.sample.chartest.desc, 'Test for CHARs' 129 | equ r.sample.chartest._, 'Character data here!' 130 | equ r.sample.cdatatest.desc, 'Test for CDATA' 131 | equ r.sample.cdatatest.misc, 'true' 132 | equ r.sample.cdatatest._, 'CDATA here!' 133 | equ r.sample.nochartest.desc, 'No data' 134 | equ r.sample.nochartest.misc, 'false' 135 | equ r.sample.listtest.item[0].subitem[0], 'Foo(1)' 136 | equ r.sample.listtest.item[0].subitem[1], 'Foo(2)' 137 | equ r.sample.listtest.item[0].subitem[2], 'Foo(3)' 138 | equ r.sample.listtest.item[0].subitem[3], 'Foo(4)' 139 | equ r.sample.listtest.item[1], 'Qux.' 140 | equ r.sample.listtest.item[2], 'Quux.' 141 | equ r.sample.listtest.single, 'Single' 142 | equ r.sample.listtest.attr, 'Attribute') 143 | 144 | 'test parse with explicitChildren': skeleton(explicitChildren: true, (r) -> 145 | console.log 'Result object: ' + util.inspect r, false, 10 146 | equ r.sample.$$.chartest[0].$.desc, 'Test for CHARs' 147 | equ r.sample.$$.chartest[0]._, 'Character data here!' 148 | equ r.sample.$$.cdatatest[0].$.desc, 'Test for CDATA' 149 | equ r.sample.$$.cdatatest[0].$.misc, 'true' 150 | equ r.sample.$$.cdatatest[0]._, 'CDATA here!' 151 | equ r.sample.$$.nochartest[0].$.desc, 'No data' 152 | equ r.sample.$$.nochartest[0].$.misc, 'false' 153 | equ r.sample.$$.listtest[0].$$.item[0]._, '\n This is\n \n character\n \n data!\n \n ' 154 | equ r.sample.$$.listtest[0].$$.item[0].$$.subitem[0], 'Foo(1)' 155 | equ r.sample.$$.listtest[0].$$.item[0].$$.subitem[1], 'Foo(2)' 156 | equ r.sample.$$.listtest[0].$$.item[0].$$.subitem[2], 'Foo(3)' 157 | equ r.sample.$$.listtest[0].$$.item[0].$$.subitem[3], 'Foo(4)' 158 | equ r.sample.$$.listtest[0].$$.item[1], 'Qux.' 159 | equ r.sample.$$.listtest[0].$$.item[2], 'Quux.' 160 | equ r.sample.$$.nochildrentest[0].$$, undefined 161 | # determine number of items in object 162 | equ Object.keys(r.sample.$$.tagcasetest[0].$$).length, 3) 163 | 164 | 'test parse with explicitChildren and preserveChildrenOrder': skeleton(explicitChildren: true, preserveChildrenOrder: true, (r) -> 165 | console.log 'Result object: ' + util.inspect r, false, 10 166 | equ r.sample.$$[10]['#name'], 'ordertest' 167 | equ r.sample.$$[10].$$[0]['#name'], 'one' 168 | equ r.sample.$$[10].$$[0]._, '1' 169 | equ r.sample.$$[10].$$[1]['#name'], 'two' 170 | equ r.sample.$$[10].$$[1]._, '2' 171 | equ r.sample.$$[10].$$[2]['#name'], 'three' 172 | equ r.sample.$$[10].$$[2]._, '3' 173 | equ r.sample.$$[10].$$[3]['#name'], 'one' 174 | equ r.sample.$$[10].$$[3]._, '4' 175 | equ r.sample.$$[10].$$[4]['#name'], 'two' 176 | equ r.sample.$$[10].$$[4]._, '5' 177 | equ r.sample.$$[10].$$[5]['#name'], 'three' 178 | equ r.sample.$$[10].$$[5]._, '6') 179 | 180 | 'test parse with explicitChildren and charsAsChildren and preserveChildrenOrder': skeleton(explicitChildren: true, preserveChildrenOrder: true, charsAsChildren: true, (r) -> 181 | console.log 'Result object: ' + util.inspect r, false, 10 182 | equ r.sample.$$[10]['#name'], 'ordertest' 183 | equ r.sample.$$[10].$$[0]['#name'], 'one' 184 | equ r.sample.$$[10].$$[0]._, '1' 185 | equ r.sample.$$[10].$$[1]['#name'], 'two' 186 | equ r.sample.$$[10].$$[1]._, '2' 187 | equ r.sample.$$[10].$$[2]['#name'], 'three' 188 | equ r.sample.$$[10].$$[2]._, '3' 189 | equ r.sample.$$[10].$$[3]['#name'], 'one' 190 | equ r.sample.$$[10].$$[3]._, '4' 191 | equ r.sample.$$[10].$$[4]['#name'], 'two' 192 | equ r.sample.$$[10].$$[4]._, '5' 193 | equ r.sample.$$[10].$$[5]['#name'], 'three' 194 | equ r.sample.$$[10].$$[5]._, '6' 195 | 196 | # test text ordering with XML nodes in the middle 197 | equ r.sample.$$[17]['#name'], 'textordertest' 198 | equ r.sample.$$[17].$$[0]['#name'], '__text__' 199 | equ r.sample.$$[17].$$[0]._, 'this is text with ' 200 | equ r.sample.$$[17].$$[1]['#name'], 'b' 201 | equ r.sample.$$[17].$$[1]._, 'markup' 202 | equ r.sample.$$[17].$$[2]['#name'], 'em' 203 | equ r.sample.$$[17].$$[2]._, 'like this' 204 | equ r.sample.$$[17].$$[3]['#name'], '__text__' 205 | equ r.sample.$$[17].$$[3]._, ' in the middle') 206 | 207 | 'test parse with explicitChildren and charsAsChildren and preserveChildrenOrder and includeWhiteChars': skeleton(explicitChildren: true, preserveChildrenOrder: true, charsAsChildren: true, includeWhiteChars: true, (r) -> 208 | console.log 'Result object: ' + util.inspect r, false, 10 209 | equ r.sample.$$[35]['#name'], 'textordertest' 210 | equ r.sample.$$[35].$$[0]['#name'], '__text__' 211 | equ r.sample.$$[35].$$[0]._, 'this is text with ' 212 | equ r.sample.$$[35].$$[1]['#name'], 'b' 213 | equ r.sample.$$[35].$$[1]._, 'markup' 214 | equ r.sample.$$[35].$$[2]['#name'], '__text__' 215 | equ r.sample.$$[35].$$[2]._, ' ' 216 | equ r.sample.$$[35].$$[3]['#name'], 'em' 217 | equ r.sample.$$[35].$$[3]._, 'like this' 218 | equ r.sample.$$[35].$$[4]['#name'], '__text__' 219 | equ r.sample.$$[35].$$[4]._, ' in the middle') 220 | 221 | 'test parse with explicitChildren and charsAsChildren and preserveChildrenOrder and includeWhiteChars and normalize': skeleton(explicitChildren: true, preserveChildrenOrder: true, charsAsChildren: true, includeWhiteChars: true, normalize: true, (r) -> 222 | console.log 'Result object: ' + util.inspect r, false, 10 223 | # normalized whitespace-only text node becomes empty string 224 | equ r.sample.$$[35]['#name'], 'textordertest' 225 | equ r.sample.$$[35].$$[0]['#name'], '__text__' 226 | equ r.sample.$$[35].$$[0]._, 'this is text with' 227 | equ r.sample.$$[35].$$[1]['#name'], 'b' 228 | equ r.sample.$$[35].$$[1]._, 'markup' 229 | equ r.sample.$$[35].$$[2]['#name'], '__text__' 230 | equ r.sample.$$[35].$$[2]._, '' 231 | equ r.sample.$$[35].$$[3]['#name'], 'em' 232 | equ r.sample.$$[35].$$[3]._, 'like this' 233 | equ r.sample.$$[35].$$[4]['#name'], '__text__' 234 | equ r.sample.$$[35].$$[4]._, 'in the middle') 235 | 236 | 'test element without children': skeleton(explicitChildren: true, (r) -> 237 | console.log 'Result object: ' + util.inspect r, false, 10 238 | equ r.sample.$$.nochildrentest[0].$$, undefined) 239 | 240 | 'test parse with explicitChildren and charsAsChildren': skeleton(explicitChildren: true, charsAsChildren: true, (r) -> 241 | console.log 'Result object: ' + util.inspect r, false, 10 242 | equ r.sample.$$.chartest[0].$$._, 'Character data here!' 243 | equ r.sample.$$.cdatatest[0].$$._, 'CDATA here!' 244 | equ r.sample.$$.listtest[0].$$.item[0].$$._, '\n This is\n \n character\n \n data!\n \n ' 245 | # determine number of items in object 246 | equ Object.keys(r.sample.$$.tagcasetest[0].$$).length, 3) 247 | 248 | 'test text trimming, normalize': skeleton(trim: true, normalize: true, (r) -> 249 | equ r.sample.whitespacetest[0]._, 'Line One Line Two') 250 | 251 | 'test text trimming, no normalizing': skeleton(trim: true, normalize: false, (r) -> 252 | equ r.sample.whitespacetest[0]._, 'Line One\n Line Two') 253 | 254 | 'test text no trimming, normalize': skeleton(trim: false, normalize: true, (r) -> 255 | equ r.sample.whitespacetest[0]._, 'Line One Line Two') 256 | 257 | 'test text no trimming, no normalize': skeleton(trim: false, normalize: false, (r) -> 258 | equ r.sample.whitespacetest[0]._, '\n Line One\n Line Two\n ') 259 | 260 | 'test enabled root node elimination': skeleton(__xmlString: '', explicitRoot: false, (r) -> 261 | console.log 'Result object: ' + util.inspect r, false, 10 262 | assert.deepEqual r, '') 263 | 264 | 'test disabled root node elimination': skeleton(__xmlString: '', explicitRoot: true, (r) -> 265 | assert.deepEqual r, {root: ''}) 266 | 267 | 'test default empty tag result': skeleton(undefined, (r) -> 268 | assert.deepEqual r.sample.emptytest, ['']) 269 | 270 | 'test empty tag result specified null': skeleton(emptyTag: null, (r) -> 271 | equ r.sample.emptytest[0], null) 272 | 273 | 'test invalid empty XML file': skeleton(__xmlString: ' ', (r) -> 274 | equ r, null) 275 | 276 | 'test enabled normalizeTags': skeleton(normalizeTags: true, (r) -> 277 | console.log 'Result object: ' + util.inspect r, false, 10 278 | equ Object.keys(r.sample.tagcasetest).length, 1) 279 | 280 | 'test parse with custom char and attribute object keys': skeleton(attrkey: 'attrobj', charkey: 'charobj', (r) -> 281 | console.log 'Result object: ' + util.inspect r, false, 10 282 | equ r.sample.chartest[0].attrobj.desc, 'Test for CHARs' 283 | equ r.sample.chartest[0].charobj, 'Character data here!' 284 | equ r.sample.cdatatest[0].attrobj.desc, 'Test for CDATA' 285 | equ r.sample.cdatatest[0].attrobj.misc, 'true' 286 | equ r.sample.cdatatest[0].charobj, 'CDATA here!' 287 | equ r.sample.cdatawhitespacetest[0].charobj, ' ' 288 | equ r.sample.nochartest[0].attrobj.desc, 'No data' 289 | equ r.sample.nochartest[0].attrobj.misc, 'false') 290 | 291 | 'test child node without explicitArray': skeleton(explicitArray: false, (r) -> 292 | console.log 'Result object: ' + util.inspect r, false, 10 293 | equ r.sample.arraytest.item[0].subitem, 'Baz.' 294 | equ r.sample.arraytest.item[1].subitem[0], 'Foo.' 295 | equ r.sample.arraytest.item[1].subitem[1], 'Bar.') 296 | 297 | 'test child node with explicitArray': skeleton(explicitArray: true, (r) -> 298 | console.log 'Result object: ' + util.inspect r, false, 10 299 | equ r.sample.arraytest[0].item[0].subitem[0], 'Baz.' 300 | equ r.sample.arraytest[0].item[1].subitem[0], 'Foo.' 301 | equ r.sample.arraytest[0].item[1].subitem[1], 'Bar.') 302 | 303 | 'test ignore attributes': skeleton(ignoreAttrs: true, (r) -> 304 | console.log 'Result object: ' + util.inspect r, false, 10 305 | equ r.sample.chartest[0], 'Character data here!' 306 | equ r.sample.cdatatest[0], 'CDATA here!' 307 | equ r.sample.nochartest[0], '' 308 | equ r.sample.listtest[0].item[0]._, '\n This is\n \n character\n \n data!\n \n ' 309 | equ r.sample.listtest[0].item[0].subitem[0], 'Foo(1)' 310 | equ r.sample.listtest[0].item[0].subitem[1], 'Foo(2)' 311 | equ r.sample.listtest[0].item[0].subitem[2], 'Foo(3)' 312 | equ r.sample.listtest[0].item[0].subitem[3], 'Foo(4)' 313 | equ r.sample.listtest[0].item[1], 'Qux.' 314 | equ r.sample.listtest[0].item[2], 'Quux.') 315 | 316 | 'test simple callback mode': (test) -> 317 | x2js = new xml2js.Parser() 318 | fs.readFile fileName, (err, data) -> 319 | equ err, null 320 | x2js.parseString data, (err, r) -> 321 | equ err, null 322 | # just a single test to check whether we parsed anything 323 | equ r.sample.chartest[0]._, 'Character data here!' 324 | test.finish() 325 | 326 | 'test simple callback with options': (test) -> 327 | fs.readFile fileName, (err, data) -> 328 | xml2js.parseString data, 329 | trim: true 330 | normalize: true, 331 | (err, r) -> 332 | console.log r 333 | equ r.sample.whitespacetest[0]._, 'Line One Line Two' 334 | test.finish() 335 | 336 | 'test double parse': (test) -> 337 | x2js = new xml2js.Parser() 338 | fs.readFile fileName, (err, data) -> 339 | equ err, null 340 | x2js.parseString data, (err, r) -> 341 | equ err, null 342 | # make sure we parsed anything 343 | equ r.sample.chartest[0]._, 'Character data here!' 344 | x2js.parseString data, (err, r) -> 345 | equ err, null 346 | equ r.sample.chartest[0]._, 'Character data here!' 347 | test.finish() 348 | 349 | 'test element with garbage XML': (test) -> 350 | x2js = new xml2js.Parser() 351 | xmlString = "<<>fdfsdfsdf<><<><<><>!<>!!." 352 | x2js.parseString xmlString, (err, result) -> 353 | assert.notEqual err, null 354 | test.finish() 355 | 356 | 'test simple function without options': (test) -> 357 | fs.readFile fileName, (err, data) -> 358 | xml2js.parseString data, (err, r) -> 359 | equ err, null 360 | equ r.sample.chartest[0]._, 'Character data here!' 361 | test.finish() 362 | 363 | 'test simple function with options': (test) -> 364 | fs.readFile fileName, (err, data) -> 365 | # well, {} still counts as option, right? 366 | xml2js.parseString data, {}, (err, r) -> 367 | equ err, null 368 | equ r.sample.chartest[0]._, 'Character data here!' 369 | test.finish() 370 | 371 | 'test async execution': (test) -> 372 | fs.readFile fileName, (err, data) -> 373 | xml2js.parseString data, async: true, (err, r) -> 374 | equ err, null 375 | equ r.sample.chartest[0]._, 'Character data here!' 376 | test.finish() 377 | 378 | 'test validator': skeleton(validator: validator, (r) -> 379 | console.log 'Result object: ' + util.inspect r, false, 10 380 | equ typeof r.sample.validatortest[0].stringtest[0], 'string' 381 | equ typeof r.sample.validatortest[0].numbertest[0], 'number' 382 | assert.ok r.sample.validatortest[0].emptyarray[0].item instanceof Array 383 | equ r.sample.validatortest[0].emptyarray[0].item.length, 0 384 | assert.ok r.sample.validatortest[0].oneitemarray[0].item instanceof Array 385 | equ r.sample.validatortest[0].oneitemarray[0].item.length, 1 386 | equ r.sample.validatortest[0].oneitemarray[0].item[0], 'Bar.' 387 | assert.ok r.sample.arraytest[0].item instanceof Array 388 | equ r.sample.arraytest[0].item.length, 2 389 | equ r.sample.arraytest[0].item[0].subitem[0], 'Baz.' 390 | equ r.sample.arraytest[0].item[1].subitem[0], 'Foo.' 391 | equ r.sample.arraytest[0].item[1].subitem[1], 'Bar.') 392 | 393 | 'test validation error': (test) -> 394 | x2js = new xml2js.Parser({validator: validator}) 395 | x2js.parseString '', (err, r) -> 396 | equ err.message, 'Validation error!' 397 | test.finish() 398 | 399 | 'test error throwing': (test) -> 400 | xml = 'content is ok' 401 | try 402 | xml2js.parseString xml, (err, parsed) -> 403 | throw new Error 'error throwing in callback' 404 | throw new Error 'error throwing outside' 405 | catch e 406 | # the stream is finished by the time the parseString method is called 407 | # so the callback, which is synchronous, will bubble the inner error 408 | # out to here, make sure that happens 409 | equ e.message, 'error throwing in callback' 410 | test.finish() 411 | 412 | 'test error throwing after an error (async)': (test) -> 413 | xml = 'content is ok' 414 | nCalled = 0 415 | xml2js.parseString xml, async: true, (err, parsed) -> 416 | # Make sure no future changes break this 417 | ++nCalled 418 | if nCalled > 1 419 | test.fail 'callback called multiple times' 420 | # SAX Parser throws multiple errors when processing async. We need to catch and return the first error 421 | # and then squelch the rest. The only way to test this is to defer the test finish call until after the 422 | # current stack processes, which, if the test would fail, would contain and throw the additional errors 423 | setTimeout test.finish.bind test 424 | 425 | 'test xmlns': skeleton(xmlns: true, (r) -> 426 | console.log 'Result object: ' + util.inspect r, false, 10 427 | equ r.sample["pfx:top"][0].$ns.local, 'top' 428 | equ r.sample["pfx:top"][0].$ns.uri, 'http://foo.com' 429 | equ r.sample["pfx:top"][0].$["pfx:attr"].value, 'baz' 430 | equ r.sample["pfx:top"][0].$["pfx:attr"].local, 'attr' 431 | equ r.sample["pfx:top"][0].$["pfx:attr"].uri, 'http://foo.com' 432 | equ r.sample["pfx:top"][0].middle[0].$ns.local, 'middle' 433 | equ r.sample["pfx:top"][0].middle[0].$ns.uri, 'http://bar.com') 434 | 435 | 'test callback should be called once': (test) -> 436 | xml = 'test' 437 | i = 0 438 | try 439 | xml2js.parseString xml, (err, parsed) -> 440 | i = i + 1 441 | # throw something custom 442 | throw new Error 'Custom error message' 443 | catch e 444 | equ i, 1 445 | equ e.message, 'Custom error message' 446 | test.finish() 447 | 448 | 'test no error event after end': (test) -> 449 | xml = 'test' 450 | i = 0 451 | x2js = new xml2js.Parser() 452 | x2js.on 'error', -> 453 | i = i + 1 454 | 455 | x2js.on 'end', -> 456 | #This is a userland callback doing something with the result xml. 457 | #Errors in here should not be passed to the parser's 'error' callbacks 458 | #Errors here should be propagated so that the user can see them and 459 | #fix them. 460 | throw new Error('some error in user-land') 461 | 462 | try 463 | x2js.parseString(xml) 464 | catch e 465 | equ e.message, 'some error in user-land' 466 | 467 | equ i, 0 468 | test.finish() 469 | 470 | 'test empty CDATA': (test) -> 471 | xml = '5850440872586764820' 472 | xml2js.parseString xml, (err, parsed) -> 473 | equ parsed.xml.Label[0], '' 474 | test.finish() 475 | 476 | 'test CDATA whitespaces result': (test) -> 477 | xml = '' 478 | xml2js.parseString xml, (err, parsed) -> 479 | equ parsed.spacecdatatest, ' ' 480 | test.finish() 481 | 482 | 'test escaped CDATA result': (test) -> 483 | xml = ']]>' 484 | xml2js.parseString xml, (err, parsed) -> 485 | equ parsed.spacecdatatest, ']]>' 486 | test.finish() 487 | 488 | 'test escaped CDATA result': (test) -> 489 | xml = ']]>' 490 | xml2js.parseString xml, (err, parsed) -> 491 | equ parsed.spacecdatatest, ']]>' 492 | test.finish() 493 | 494 | 'test non-strict parsing': (test) -> 495 | html = '
' 496 | xml2js.parseString html, strict: false, (err, parsed) -> 497 | equ err, null 498 | test.finish() 499 | 500 | 'test construction with new and without': (test) -> 501 | demo = 'Bar' 502 | withNew = new xml2js.Parser 503 | withNew.parseString demo, (err, resWithNew) -> 504 | equ err, null 505 | withoutNew = xml2js.Parser() 506 | withoutNew.parseString demo, (err, resWithoutNew) -> 507 | equ err, null 508 | assert.deepEqual resWithNew, resWithoutNew 509 | test.finish() 510 | 511 | 'test not closed but well formed xml': (test) -> 512 | xml = "" 513 | xml2js.parseString xml, (err, parsed) -> 514 | assert.equal err.message, 'Unclosed root tag\nLine: 0\nColumn: 6\nChar: ' 515 | test.finish() 516 | 517 | 'test cdata-named node': (test) -> 518 | xml = "hello" 519 | xml2js.parseString xml, (err, parsed) -> 520 | assert.equal parsed.test.cdata[0], 'hello' 521 | test.finish() 522 | 523 | 'test onend with empty xml': (test) -> 524 | xml = "" 525 | xml2js.parseString xml, (err, parsed) -> 526 | assert.equal parsed, null 527 | test.finish() 528 | 529 | 'test parsing null': (test) -> 530 | xml = null 531 | xml2js.parseString xml, (err, parsed) -> 532 | assert.notEqual err, null 533 | test.finish() 534 | 535 | 'test parsing undefined': (test) -> 536 | xml = undefined 537 | xml2js.parseString xml, (err, parsed) -> 538 | assert.notEqual err, null 539 | test.finish() 540 | 541 | 'test chunked processing': (test) -> 542 | xml = "abcdefghijklmnopqrstuvwxyz" 543 | xml2js.parseString xml, chunkSize: 10, (err, parsed) -> 544 | equ err, null 545 | equ parsed.longstuff, 'abcdefghijklmnopqrstuvwxyz' 546 | test.finish() 547 | 548 | 'test single attrNameProcessors': skeleton(attrNameProcessors: [nameToUpperCase], (r)-> 549 | console.log 'Result object: ' + util.inspect r, false, 10 550 | equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('CAMELCASEATTR'), true 551 | equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('LOWERCASEATTR'), true) 552 | 553 | 'test multiple attrNameProcessors': skeleton(attrNameProcessors: [nameToUpperCase, nameCutoff], (r)-> 554 | console.log 'Result object: ' + util.inspect r, false, 10 555 | equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('CAME'), true 556 | equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('LOWE'), true) 557 | 558 | 'test single attrValueProcessors': skeleton(attrValueProcessors: [nameToUpperCase], (r)-> 559 | console.log 'Result object: ' + util.inspect r, false, 10 560 | equ r.sample.attrValueProcessTest[0].$.camelCaseAttr, 'CAMELCASEATTRVALUE' 561 | equ r.sample.attrValueProcessTest[0].$.lowerCaseAttr, 'LOWERCASEATTRVALUE') 562 | 563 | 'test multiple attrValueProcessors': skeleton(attrValueProcessors: [nameToUpperCase, nameCutoff], (r)-> 564 | console.log 'Result object: ' + util.inspect r, false, 10 565 | equ r.sample.attrValueProcessTest[0].$.camelCaseAttr, 'CAME' 566 | equ r.sample.attrValueProcessTest[0].$.lowerCaseAttr, 'LOWE') 567 | 568 | 'test single valueProcessors': skeleton(valueProcessors: [nameToUpperCase], (r)-> 569 | console.log 'Result object: ' + util.inspect r, false, 10 570 | equ r.sample.valueProcessTest[0], 'SOME VALUE') 571 | 572 | 'test multiple valueProcessors': skeleton(valueProcessors: [nameToUpperCase, nameCutoff], (r)-> 573 | console.log 'Result object: ' + util.inspect r, false, 10 574 | equ r.sample.valueProcessTest[0], 'SOME') 575 | 576 | 'test single tagNameProcessors': skeleton(tagNameProcessors: [nameToUpperCase], (r)-> 577 | console.log 'Result object: ' + util.inspect r, false, 10 578 | equ r.hasOwnProperty('SAMPLE'), true 579 | equ r.SAMPLE.hasOwnProperty('TAGNAMEPROCESSTEST'), true) 580 | 581 | 'test single tagNameProcessors in simple callback': (test) -> 582 | fs.readFile fileName, (err, data) -> 583 | xml2js.parseString data, tagNameProcessors: [nameToUpperCase], (err, r)-> 584 | console.log 'Result object: ' + util.inspect r, false, 10 585 | equ r.hasOwnProperty('SAMPLE'), true 586 | equ r.SAMPLE.hasOwnProperty('TAGNAMEPROCESSTEST'), true 587 | test.finish() 588 | 589 | 'test multiple tagNameProcessors': skeleton(tagNameProcessors: [nameToUpperCase, nameCutoff], (r)-> 590 | console.log 'Result object: ' + util.inspect r, false, 10 591 | equ r.hasOwnProperty('SAMP'), true 592 | equ r.SAMP.hasOwnProperty('TAGN'), true) 593 | 594 | 'test attrValueProcessors key param': skeleton(attrValueProcessors: [replaceValueByName], (r)-> 595 | console.log 'Result object: ' + util.inspect r, false, 10 596 | equ r.sample.attrValueProcessTest[0].$.camelCaseAttr, 'camelCaseAttr' 597 | equ r.sample.attrValueProcessTest[0].$.lowerCaseAttr, 'lowerCaseAttr') 598 | 599 | 'test valueProcessors key param': skeleton(valueProcessors: [replaceValueByName], (r)-> 600 | console.log 'Result object: ' + util.inspect r, false, 10 601 | equ r.sample.valueProcessTest[0], 'valueProcessTest') 602 | 603 | 'test parseStringPromise parsing': (test) -> 604 | x2js = new xml2js.Parser() 605 | readFilePromise(fileName).then (data) -> 606 | x2js.parseStringPromise data 607 | .then (r) -> 608 | # just a single test to check whether we parsed anything 609 | equ r.sample.chartest[0]._, 'Character data here!' 610 | test.finish() 611 | .catch (err) -> 612 | test.fail('Should not error') 613 | 614 | 'test parseStringPromise with bad input': (test) -> 615 | x2js = new xml2js.Parser() 616 | x2js.parseStringPromise("< a moose bit my sister>").then (r) -> 617 | test.fail('Should fail') 618 | .catch (err) -> 619 | assert.notEqual err, null 620 | test.finish() 621 | 622 | 'test global parseStringPromise parsing': (test) -> 623 | readFilePromise(fileName).then (data) -> 624 | xml2js.parseStringPromise data 625 | .then (r) -> 626 | assert.notEqual r, null 627 | equ r.sample.listtest[0].item[0].subitem[0], 'Foo(1)' 628 | test.finish() 629 | .catch (err) -> 630 | test.fail('Should not error') 631 | 632 | 'test global parseStringPromise with options': (test) -> 633 | readFilePromise(fileName).then (data) -> 634 | xml2js.parseStringPromise data, 635 | trim: true 636 | normalize: true 637 | .then (r) -> 638 | assert.notEqual r, null 639 | equ r.sample.whitespacetest[0]._, 'Line One Line Two' 640 | test.finish() 641 | .catch (err) -> 642 | test.fail('Should not error') 643 | 644 | 'test global parseStringPromise with bad input': (test) -> 645 | xml2js.parseStringPromise("< a moose bit my sister>").then (r) -> 646 | test.fail('Should fail') 647 | .catch (err) -> 648 | assert.notEqual err, null 649 | test.finish() 650 | -------------------------------------------------------------------------------- /test/processors.test.coffee: -------------------------------------------------------------------------------- 1 | processors = require '../lib/processors' 2 | xml2js = require '../lib/xml2js' 3 | assert = require 'assert' 4 | equ = assert.equal 5 | 6 | parseNumbersExceptAccount = (value, key) -> 7 | if (key == 'accountNumber') 8 | return value; 9 | return processors.parseNumbers(value); 10 | 11 | module.exports = 12 | 'test normalize': (test) -> 13 | demo = 'This shOUld BE loWErcase' 14 | result = processors.normalize demo 15 | equ result, 'this should be lowercase' 16 | test.done() 17 | 18 | 'test firstCharLowerCase': (test) -> 19 | demo = 'ThiS SHould OnlY LOwercase the fIRST cHar' 20 | result = processors.firstCharLowerCase demo 21 | equ result, 'thiS SHould OnlY LOwercase the fIRST cHar' 22 | test.done() 23 | 24 | 'test stripPrefix': (test) -> 25 | demo = 'stripMe:DoNotTouch' 26 | result = processors.stripPrefix demo 27 | equ result, 'DoNotTouch' 28 | test.done() 29 | 30 | 'test stripPrefix, ignore xmlns': (test) -> 31 | demo = 'xmlns:shouldHavePrefix' 32 | result = processors.stripPrefix demo 33 | equ result, 'xmlns:shouldHavePrefix' 34 | test.done() 35 | 36 | 'test parseNumbers': (test) -> 37 | equ processors.parseNumbers('0'), 0 38 | equ processors.parseNumbers('123'), 123 39 | equ processors.parseNumbers('15.56'), 15.56 40 | equ processors.parseNumbers('10.00'), 10 41 | test.done() 42 | 43 | 'test parseBooleans': (test) -> 44 | equ processors.parseBooleans('true'), true 45 | equ processors.parseBooleans('True'), true 46 | equ processors.parseBooleans('TRUE'), true 47 | equ processors.parseBooleans('false'), false 48 | equ processors.parseBooleans('False'), false 49 | equ processors.parseBooleans('FALSE'), false 50 | equ processors.parseBooleans('truex'), 'truex' 51 | equ processors.parseBooleans('xtrue'), 'xtrue' 52 | equ processors.parseBooleans('x'), 'x' 53 | equ processors.parseBooleans(''), '' 54 | test.done() 55 | 56 | 'test a processor that filters by node name': (test) -> 57 | xml = '0012345123.45' 58 | options = { valueProcessors: [parseNumbersExceptAccount] } 59 | xml2js.parseString xml, options, (err, parsed) -> 60 | equ parsed.account.accountNumber, '0012345' 61 | equ parsed.account.balance, 123.45 62 | test.finish() 63 | 64 | 'test a processor that filters by attr name': (test) -> 65 | xml = '' 66 | options = { attrValueProcessors: [parseNumbersExceptAccount] } 67 | xml2js.parseString xml, options, (err, parsed) -> 68 | equ parsed.account.$.accountNumber, '0012345' 69 | equ parsed.account.$.balance, 123.45 70 | test.finish() --------------------------------------------------------------------------------