├── .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 | [](https://travis-ci.org/Leonidas-from-XIV/node-xml2js)
483 | [](https://coveralls.io/r/Leonidas-from-XIV/node-xml2js?branch=master)
484 | [](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 = '5850440872586764820'
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 | &<>
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()
--------------------------------------------------------------------------------