From 99cb8fd97e6dcbce2aa3980679602db823a8a77d Mon Sep 17 00:00:00 2001 From: Yousuf Almarzooqi Date: Tue, 12 Dec 2017 21:39:07 +0400 Subject: [PATCH] Committed by npm script. --- .editorconfig | 6 +- .eslintrc | 205 - .eslintrc.json | 17 + .eslintrcignore | 1 - .jshintrc | 4 - .npmignore | 1 + .vscode/launch.json | 2 +- README.md | 10 +- bin/cli-helper.js | 47 + bin/cli.js | 78 +- lib/common.js | 77 - lib/js2xml.js | 169 +- lib/json2xml.js | 3 +- lib/options-helper.js | 35 + lib/xml2js.js | 58 +- lib/xml2json.js | 7 +- package-lock.json | 6 +- package.json | 14 +- test/browse-jasmine/bundle.js | 9121 +---------------- test/cli-helper_test.js | 76 + test/cli_test.js | 11 +- test/common_test.js | 133 - test/jasmine.json | 2 +- test/js2xml-issues_test.js | 379 + test/js2xml-options_test.js | 380 + test/js2xml_test.js | 751 -- test/options-helper_test.js | 68 + test/test-items.js | 22 +- test/test-pareja.js | 5 - test/usage-example.js | 3 +- test/xml2js-issues_test.js | 356 + test/xml2js-keys_test.js | 258 + ...{xml2js_test.js => xml2js-options_test.js} | 76 +- 33 files changed, 1854 insertions(+), 10527 deletions(-) delete mode 100644 .eslintrc create mode 100644 .eslintrc.json delete mode 100644 .eslintrcignore delete mode 100644 .jshintrc create mode 100644 bin/cli-helper.js delete mode 100644 lib/common.js create mode 100644 lib/options-helper.js create mode 100644 test/cli-helper_test.js delete mode 100644 test/common_test.js create mode 100644 test/js2xml-issues_test.js create mode 100644 test/js2xml-options_test.js delete mode 100644 test/js2xml_test.js create mode 100644 test/options-helper_test.js delete mode 100644 test/test-pareja.js create mode 100644 test/xml2js-issues_test.js create mode 100644 test/xml2js-keys_test.js rename test/{xml2js_test.js => xml2js-options_test.js} (90%) diff --git a/.editorconfig b/.editorconfig index a3bc264..8768cc1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,11 +7,11 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true -[*.{js}] +[*.{js,ts,json,yml}] charset = utf-8 indent_style = space indent_size = 2 -[{package.json,.travis.yml}] +[*.{xml}] indent_style = space -indent_size = 2 +indent_size = 4 diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index e0150e1..0000000 --- a/.eslintrc +++ /dev/null @@ -1,205 +0,0 @@ -ecmaFeatures: - modules: true - jsx: true -env: - amd: true - browser: true - es6: true - jquery: true - node: true -# http://eslint.org/docs/rules/ -rules: - # Possible Errors - comma-dangle: [2, never] - no-cond-assign: 2 - no-console: 0 - no-constant-condition: 2 - no-control-regex: 2 - no-debugger: 2 - no-dupe-args: 2 - no-dupe-keys: 2 - no-duplicate-case: 2 - no-empty: 2 - no-empty-character-class: 2 - no-ex-assign: 2 - no-extra-boolean-cast: 2 - no-extra-parens: 0 - no-extra-semi: 2 - no-func-assign: 2 - no-inner-declarations: [2, functions] - no-invalid-regexp: 2 - no-irregular-whitespace: 2 - no-negated-in-lhs: 2 - no-obj-calls: 2 - no-regex-spaces: 2 - no-sparse-arrays: 2 - no-unexpected-multiline: 2 - no-unreachable: 2 - use-isnan: 2 - valid-jsdoc: 0 - valid-typeof: 2 - # Best Practices - accessor-pairs: 2 - block-scoped-var: 0 - complexity: [2, 10] - consistent-return: 0 - curly: 0 - default-case: 0 - dot-location: 0 - dot-notation: 0 - eqeqeq: 2 - guard-for-in: 2 - no-alert: 2 - no-caller: 2 - no-case-declarations: 2 - no-div-regex: 2 - no-else-return: 0 - no-empty-label: 2 - no-empty-pattern: 2 - no-eq-null: 2 - no-eval: 2 - no-extend-native: 2 - no-extra-bind: 2 - no-fallthrough: 2 - no-floating-decimal: 0 - no-implicit-coercion: 0 - no-implied-eval: 2 - no-invalid-this: 0 - no-iterator: 2 - no-labels: 0 - no-lone-blocks: 2 - no-loop-func: 2 - no-magic-number: 0 - no-multi-spaces: 0 - no-multi-str: 0 - no-native-reassign: 2 - no-new-func: 2 - no-new-wrappers: 2 - no-new: 2 - no-octal-escape: 2 - no-octal: 2 - no-proto: 2 - no-redeclare: 2 - no-return-assign: 2 - no-script-url: 2 - no-self-compare: 2 - no-sequences: 0 - no-throw-literal: 0 - no-unused-expressions: 2 - no-useless-call: 2 - no-useless-concat: 2 - no-void: 2 - no-warning-comments: 0 - no-with: 2 - radix: 2 - vars-on-top: 0 - wrap-iife: 2 - yoda: 0 - # Strict - strict: 0 - # Variables - init-declarations: 0 - no-catch-shadow: 2 - no-delete-var: 2 - no-label-var: 2 - no-shadow-restricted-names: 2 - no-shadow: 0 - no-undef-init: 2 - no-undef: 0 - no-undefined: 0 - no-unused-vars: 0 - no-use-before-define: 0 - # Node.js and CommonJS - callback-return: 2 - global-require: 2 - handle-callback-err: 2 - no-mixed-requires: 0 - no-new-require: 0 - no-path-concat: 2 - no-process-exit: 2 - no-restricted-modules: 0 - no-sync: 0 - # Stylistic Issues - array-bracket-spacing: 0 - block-spacing: 0 - brace-style: 0 - camelcase: 0 - comma-spacing: 0 - comma-style: 0 - computed-property-spacing: 0 - consistent-this: 0 - eol-last: 0 - func-names: 0 - func-style: 0 - id-length: 0 - id-match: 0 - indent: 0 - jsx-quotes: 0 - key-spacing: 0 - linebreak-style: 0 - lines-around-comment: 0 - max-depth: 0 - max-len: 0 - max-nested-callbacks: 0 - max-params: 0 - max-statements: [2, 30] - new-cap: 0 - new-parens: 0 - newline-after-var: 0 - no-array-constructor: 0 - no-bitwise: 0 - no-continue: 0 - no-inline-comments: 0 - no-lonely-if: 0 - no-mixed-spaces-and-tabs: 0 - no-multiple-empty-lines: 0 - no-negated-condition: 0 - no-nested-ternary: 0 - no-new-object: 0 - no-plusplus: 0 - no-restricted-syntax: 0 - no-spaced-func: 0 - no-ternary: 0 - no-trailing-spaces: 0 - no-underscore-dangle: 0 - no-unneeded-ternary: 0 - object-curly-spacing: 0 - one-var: 0 - operator-assignment: 0 - operator-linebreak: 0 - padded-blocks: 0 - quote-props: 0 - quotes: 0 - require-jsdoc: 0 - semi-spacing: 0 - semi: 0 - sort-vars: 0 - space-after-keywords: 0 - space-before-blocks: 0 - space-before-function-paren: 0 - space-before-keywords: 0 - space-in-parens: 0 - space-infix-ops: 0 - space-return-throw-case: 0 - space-unary-ops: 0 - spaced-comment: 0 - wrap-regex: 0 - # ECMAScript 6 - arrow-body-style: 0 - arrow-parens: 0 - arrow-spacing: 0 - constructor-super: 0 - generator-star-spacing: 0 - no-arrow-condition: 0 - no-class-assign: 0 - no-const-assign: 0 - no-dupe-class-members: 0 - no-this-before-super: 0 - no-var: 0 - object-shorthand: 0 - prefer-arrow-callback: 0 - prefer-const: 0 - prefer-reflect: 0 - prefer-spread: 0 - prefer-template: 0 - require-yield: 0 \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..5e771e2 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,17 @@ +{ + "extends": "eslint:recommended", + "env": { + "node": true, + "browser": true + }, + "rules": { + "excludedFiles": ["**/*.min.js"], + "indent": ["error", 2], + "linebreak-style": ["error", "unix"], + "quotes": ["error", "single"], + "semi": ["error", "always"], + "no-cond-assign": ["error", "always"], + "no-console": "off", + "no-else-return": "warn" + } +} diff --git a/.eslintrcignore b/.eslintrcignore deleted file mode 100644 index 5b3b359..0000000 --- a/.eslintrcignore +++ /dev/null @@ -1 +0,0 @@ -**/*{.,-}min.js \ No newline at end of file diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 73d98ab..0000000 --- a/.jshintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "node": true, - "esnext": true -} \ No newline at end of file diff --git a/.npmignore b/.npmignore index 6697b31..8517bc1 100644 --- a/.npmignore +++ b/.npmignore @@ -2,6 +2,7 @@ node_modules/ _playground/ artwork/ test/ +doc/ package-lock.json yarn.lock *.log diff --git a/.vscode/launch.json b/.vscode/launch.json index 9377ea0..a8e11b0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "type": "node", "request": "launch", "name": "Launch Program", - "program": "${workspaceRoot}\\test\\index.js", + "program": "${workspaceRoot}/test/index", "outFiles": [ "${workspaceRoot}/out/**/*.js" ] diff --git a/README.md b/README.md index 0287ec3..bb3780e 100644 --- a/README.md +++ b/README.md @@ -23,14 +23,14 @@ Convert XML text to Javascript object / JSON text (and vice versa). ![Convert XML ↔ JS/JSON as compact or non-compact](http://nashwaan.github.io/xml-js/images/synopsis.svg) -# Motivation - -There are many XML to JavaScript object / JSON converters out there, but could not satisfy the following requirements: +# Features * **Maintain Order of Elements**: -Instead of converting `` to `{a:[{},{}],b:{}}`, I wanted to preserve order of elements by doing this: +Most libraries will convert `` to `{a:[{},{}],b:{}}` which merges any node of same name into an array. This library can creates the following to preserve the order of elements: `{"elements":[{"type":"element","name":"a"},{"type":"element","name":"b"},{"type":"element","name":"a"}]}`. +This is very important and it is the main reason why this library was created. + * **Fully XML Compliant**: Can parse: elements, attributes, texts, comments, CData, DOCTYPE, XML declarations, and Processing Instructions. @@ -41,7 +41,7 @@ Whether converting xml→json or json→xml, the result can be converted back to This library depends only on one external npm module. * **Change Property Key Name**: -Usually output of XML attributes are stored in `@attr`, `_atrr`, `$attr`, `$`, or `whatever` in order to avoid conflicting with name of sub-elements. +Usually output of XML attributes are stored in `@attr`, `_atrr`, `$attr` or `$` in order to avoid conflicting with name of sub-elements. This library store them in `attributes`, but most importantly, you can change this to whatever you like. * **Support Upwards Traversal**: diff --git a/bin/cli-helper.js b/bin/cli-helper.js new file mode 100644 index 0000000..327b44a --- /dev/null +++ b/bin/cli-helper.js @@ -0,0 +1,47 @@ +module.exports = { + + getCommandLineHelp: function (command, requiredArgs, optionalArgs) { + var reqArgs = requiredArgs.reduce(function (res, arg) {return res + ' <' + arg.arg + '>';}, ''); + var output = 'Usage: ' + command + reqArgs + ' [options]\n'; + requiredArgs.forEach(function (argument) { + output += ' <' + argument.arg + '>' + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n'; + }); + output += '\nOptions:\n'; + optionalArgs.forEach(function (argument) { + output += ' --' + argument.arg + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n'; + }); + return output; + }, + + mapCommandLineArgs: function (requiredArgs, optionalArgs) { + var options = {}, r, o, a = 2; + for (r = 0; r < requiredArgs.length; r += 1) { + if (a < process.argv.length && process.argv[a].substr(0, 1) !== '-' && process.argv[a] !== 'JASMINE_CONFIG_PATH=./jasmine.json') { + options[requiredArgs[r].option] = process.argv[a++]; + } else { + break; + } + } + for (; a < process.argv.length; a += 1) { + for (o = 0; o < optionalArgs.length; o += 1) { + if (optionalArgs[o].alias === process.argv[a].slice(1) || optionalArgs[o].arg === process.argv[a].slice(2)) { + break; + } + } + if (o < optionalArgs.length) { + switch (optionalArgs[o].type) { + case 'file': case 'string': case 'number': + if (a + 1 < process.argv.length) { + a += 1; + options[optionalArgs[o].option] = (optionalArgs[o].type === 'number' ? Number(process.argv[a]) : process.argv[a]); + } + break; + case 'flag': + options[optionalArgs[o].option] = true; break; + } + } + } + return options; + } + +}; diff --git a/bin/cli.js b/bin/cli.js index aeb4247..6b5cf02 100644 --- a/bin/cli.js +++ b/bin/cli.js @@ -1,9 +1,8 @@ #!/usr/bin/env node -/*jslint node:true*/ var fs = require('fs'); +var helper = require('./cli-helper'); var project = require('../package.json'); -var common = require('../lib/common'); var xml2json = require('../lib/xml2json'); var json2xml = require('../lib/json2xml'); @@ -11,60 +10,59 @@ var output = ''; var stream = ''; var options = {}; var requiredArgs = [ - {arg: 'src', type: 'file', option: 'src', desc: 'Input file that need to be converted.'} + { arg: 'src', type: 'file', option: 'src', desc: 'Input file that need to be converted.'} ]; var optionalArgs = [ - {arg: 'help', alias: 'h', type: 'flag', option: 'help', desc: 'Display this help content.'}, - {arg: 'version', alias: 'v', type: 'flag', option: 'version', desc: 'Display version number of this module.'}, - {arg: 'out', type: 'file', option: 'out', desc: 'Output file where the converted result should be written.'}, - {arg: 'to-json', type: 'flag', option:'toJason', desc: 'Convert.'}, - {arg: 'compact', type: 'flag', option:'compact', desc: 'Compact JSON form (see explanation in www.npmjs.com/package/xml-js).'}, - {arg: 'spaces', type: 'number', option:'spaces', desc: 'Specifies amount of space indentation in the output.'}, - {arg: 'trim', type: 'flag', option:'trim', desc: 'Any whitespaces surrounding texts will be trimmed.'}, - // {arg: 'sanitize', type: 'flag', option:'sanitize', desc: 'Special xml characters will be replaced with entity codes.'}, - {arg: 'native-type', type: 'flag', option:'nativeType', desc: 'Numbers and boolean will be converted (coerced) to native type instead of text.'}, - {arg: 'always-array', type: 'flag', option:'alwaysArray', desc: 'Every element will always be an array type (applicable if --compact is set).'}, - {arg: 'always-children', type: 'flag', option:'alwaysChildren', desc: 'Every element will always contain sub-elements (applicable if --compact is not set).'}, - {arg: 'instruction-attr', type: 'flag', option:'instructionHasAttributes', desc: 'Whether to parse contents of processing instruction as attributes.'}, - {arg: 'full-tag', type: 'flag', option:'fullTagEmptyElement', desc: 'XML elements will always be in form.'}, - {arg: 'no-decl', type: 'flag', option:'ignoreDeclaration', desc: 'Declaration instruction will be ignored.'}, - {arg: 'no-decl', type: 'flag', option:'ignoreInstruction', desc: 'Processing instruction will be ignored.'}, - {arg: 'no-attr', type: 'flag', option:'ignoreAttributes', desc: 'Attributes of elements will be ignored.'}, - {arg: 'no-text', type: 'flag', option:'ignoreText', desc: 'Texts of elements will be ignored.'}, - {arg: 'no-cdata', type: 'flag', option:'ignoreCdata', desc: 'CData of elements will be ignored.'}, - {arg: 'no-doctype', type: 'flag', option:'ignoreDoctype', desc: 'DOCTYPE of elements will be ignored.'}, - {arg: 'no-comment', type: 'flag', option:'ignoreComment', desc: 'Comments of elements will be ignored.'}, - {arg: 'text-key', type: 'string', option:'textKey', desc: 'To change the default \'text\' key.'}, - {arg: 'cdata-key', type: 'string', option:'cdataKey', desc: 'To change the default \'cdata\' key.'}, - {arg: 'doctype-key', type: 'string', option:'doctypeKey', desc: 'To change the default \'doctype\' key.'}, - {arg: 'comment-key', type: 'string', option:'commentKey', desc: 'To change the default \'comment\' key.'}, - {arg: 'attributes-key', type: 'string', option:'attributesKey', desc: 'To change the default \'attributes\' key.'}, - {arg: 'declaration-key', type: 'string', option:'declarationKey', desc: 'To change the default \'declaration\' key .'}, - {arg: 'instruction-key', type: 'string', option:'instructionKey', desc: 'To change the default \'processing instruction\' key .'}, - {arg: 'type-key', type: 'string', option:'typeKey', desc: 'To change the default \'type\' key (applicable if --compact is not set).'}, - {arg: 'name-key', type: 'string', option:'nameKey', desc: 'To change the default \'name\' key (applicable if --compact is not set).'}, - {arg: 'elements-key', type: 'string', option:'elementsKey', desc: 'To change the default \'elements\' key (applicable if --compact is not set).'} + { arg: 'help', alias: 'h', type: 'flag', option: 'help', desc: 'Display this help content.' }, + { arg: 'version', alias: 'v', type: 'flag', option: 'version', desc: 'Display version number of this module.' }, + { arg: 'out', type: 'file', option: 'out', desc: 'Output file where the converted result should be written.' }, + { arg: 'to-json', type: 'flag', option:'toJason', desc: 'Convert.' }, + { arg: 'compact', type: 'flag', option:'compact', desc: 'Compact JSON form (see explanation in www.npmjs.com/package/xml-js).' }, + { arg: 'spaces', type: 'number', option:'spaces', desc: 'Specifies amount of space indentation in the output.' }, + { arg: 'trim', type: 'flag', option:'trim', desc: 'Any whitespaces surrounding texts will be trimmed.' }, + // { arg: 'sanitize', type: 'flag', option:'sanitize', desc: 'Special xml characters will be replaced with entity codes.' }, + { arg: 'native-type', type: 'flag', option:'nativeType', desc: 'Numbers and boolean will be converted (coerced) to native type instead of text.' }, + { arg: 'always-array', type: 'flag', option:'alwaysArray', desc: 'Every element will always be an array type (applicable if --compact is set).' }, + { arg: 'always-children', type: 'flag', option:'alwaysChildren', desc: 'Every element will always contain sub-elements (applicable if --compact is not set).' }, + { arg: 'instruction-attr', type: 'flag', option:'instructionHasAttributes', desc: 'Whether to parse contents of processing instruction as attributes.' }, + { arg: 'full-tag', type: 'flag', option:'fullTagEmptyElement', desc: 'XML elements will always be in form.' }, + { arg: 'no-decl', type: 'flag', option:'ignoreDeclaration', desc: 'Declaration instruction will be ignored.' }, + { arg: 'no-decl', type: 'flag', option:'ignoreInstruction', desc: 'Processing instruction will be ignored.' }, + { arg: 'no-attr', type: 'flag', option:'ignoreAttributes', desc: 'Attributes of elements will be ignored.' }, + { arg: 'no-text', type: 'flag', option:'ignoreText', desc: 'Texts of elements will be ignored.' }, + { arg: 'no-cdata', type: 'flag', option:'ignoreCdata', desc: 'CData of elements will be ignored.' }, + { arg: 'no-doctype', type: 'flag', option:'ignoreDoctype', desc: 'DOCTYPE of elements will be ignored.' }, + { arg: 'no-comment', type: 'flag', option:'ignoreComment', desc: 'Comments of elements will be ignored.' }, + { arg: 'text-key', type: 'string', option:'textKey', desc: 'To change the default \'text\' key.' }, + { arg: 'cdata-key', type: 'string', option:'cdataKey', desc: 'To change the default \'cdata\' key.' }, + { arg: 'doctype-key', type: 'string', option:'doctypeKey', desc: 'To change the default \'doctype\' key.' }, + { arg: 'comment-key', type: 'string', option:'commentKey', desc: 'To change the default \'comment\' key.' }, + { arg: 'attributes-key', type: 'string', option:'attributesKey', desc: 'To change the default \'attributes\' key.' }, + { arg: 'declaration-key', type: 'string', option:'declarationKey', desc: 'To change the default \'declaration\' key .' }, + { arg: 'instruction-key', type: 'string', option:'instructionKey', desc: 'To change the default \'processing instruction\' key .' }, + { arg: 'type-key', type: 'string', option:'typeKey', desc: 'To change the default \'type\' key (applicable if --compact is not set).' }, + { arg: 'name-key', type: 'string', option:'nameKey', desc: 'To change the default \'name\' key (applicable if --compact is not set).' }, + { arg: 'elements-key', type: 'string', option:'elementsKey', desc: 'To change the default \'elements\' key (applicable if --compact is not set).' } ]; process.stdin.setEncoding('utf8'); process.stdin.on('readable', function () { var chunk = process.stdin.read(); if (chunk !== null) { - stream += chunk; + stream += chunk; } }); process.stdin.on('end', function () { - process.stdout.write(xml2json(stream, {}) + '\n'); + process.stdout.write(xml2json(stream, {}) + '\n'); }); -options = common.mapCommandLineArgs(requiredArgs, optionalArgs); - +options = helper.mapCommandLineArgs(requiredArgs, optionalArgs); if (options.version) { - console.log(project.version); + console.log(project.version); process.exit(0); } else if (options.help || process.argv.length <= 2 + requiredArgs.length - 1) { - console.log(common.getCommandLineHelp('xml-js', requiredArgs, optionalArgs)); + console.log(helper.getCommandLineHelp('xml-js', requiredArgs, optionalArgs)); process.exit(process.argv.length <= 2 ? 1 : 0); } else if ('src' in options) { if (fs.statSync(options.src).isFile()) { @@ -81,5 +79,5 @@ if (options.version) { process.exit(0); } } else { - process.exit(1); + process.exit(1); } diff --git a/lib/common.js b/lib/common.js deleted file mode 100644 index ee34688..0000000 --- a/lib/common.js +++ /dev/null @@ -1,77 +0,0 @@ -/*jslint node:true */ - -module.exports = { - sanitizeElement: function (text) { - return text.replace(/&/g, "&").replace(//g, ">"); - }, - // sanitizeAttribute: function (text) { - // // should escape " if attribute is enclosed in " otherwise escape ' if attribute is enclosed in ' - // return text.replace(/"/g, """).replace(/'/g, "'"); // or use ' for ' - // }, - copyOptions: function (options) { - var key, copy = {}; - for (key in options) { - if (options.hasOwnProperty(key)) { - copy[key] = options[key]; - } - } - return copy; - }, - ensureFlagExists: function (item, options) { - if (!(item in options) || typeof options[item] !== 'boolean') { - options[item] = false; - } - }, - ensureSpacesExists: function (options) { - if (!('spaces' in options) || (typeof options.spaces !== 'number' && typeof options.spaces !== 'string')) { - options.spaces = 0; - } - }, - ensureKeyExists: function (key, options) { - if (!(key + 'Key' in options) || typeof options[key + 'Key'] !== 'string') { - options[key + 'Key'] = options.compact ? '_' + key : key; - } - }, - getCommandLineHelp: function (command, requiredArgs, optionalArgs) { - var reqArgs = requiredArgs.reduce(function (res, arg) {return res + ' <' + arg.arg + '>';}, ''); - var output = 'Usage: ' + command + reqArgs + ' [options]\n'; - requiredArgs.forEach(function (argument) { - output += ' <' + argument.arg + '>' + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n'; - }); - output += '\nOptions:\n'; - optionalArgs.forEach(function (argument) { - output += ' --' + argument.arg + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n'; - }); - return output; - }, - mapCommandLineArgs: function (requiredArgs, optionalArgs) { - var options = {}, r, o, a = 2; - for (r = 0; r < requiredArgs.length; r += 1) { - if (a < process.argv.length && process.argv[a].substr(0, 1) !== '-' && process.argv[a] !== 'JASMINE_CONFIG_PATH=./jasmine.json') { - options[requiredArgs[r].option] = process.argv[a++]; - } else { - break; - } - } - for (; a < process.argv.length; a += 1) { - for (o = 0; o < optionalArgs.length; o += 1) { - if (optionalArgs[o].alias === process.argv[a].slice(1) || optionalArgs[o].arg === process.argv[a].slice(2)) { - break; - } - } - if (o < optionalArgs.length) { - switch (optionalArgs[o].type) { - case 'file': case 'string': case 'number': - if (a + 1 < process.argv.length) { - a += 1; - options[optionalArgs[o].option] = (optionalArgs[o].type === 'number' ? Number(process.argv[a]) : process.argv[a]); - } - break; - case 'flag': - options[optionalArgs[o].option] = true; break; - } - } - } - return options; - } -}; diff --git a/lib/js2xml.js b/lib/js2xml.js index 353f8ef..1b56fcf 100644 --- a/lib/js2xml.js +++ b/lib/js2xml.js @@ -1,35 +1,35 @@ -var common = require('./common'); +var helper = require('./options-helper'); function validateOptions(userOptions) { - var options = common.copyOptions(userOptions); - common.ensureFlagExists('ignoreDeclaration', options); - common.ensureFlagExists('ignoreInstruction', options); - common.ensureFlagExists('ignoreAttributes', options); - common.ensureFlagExists('ignoreText', options); - common.ensureFlagExists('ignoreComment', options); - common.ensureFlagExists('ignoreCdata', options); - common.ensureFlagExists('ignoreDoctype', options); - common.ensureFlagExists('compact', options); - common.ensureFlagExists('indentText', options); - common.ensureFlagExists('indentCdata', options); - common.ensureFlagExists('indentAttributes', options); - common.ensureFlagExists('indentInstruction', options); - common.ensureFlagExists('fullTagEmptyElement', options); - common.ensureFlagExists('noQuotesForNativeAttributes', options); - common.ensureSpacesExists(options); + var options = helper.copyOptions(userOptions); + helper.ensureFlagExists('ignoreDeclaration', options); + helper.ensureFlagExists('ignoreInstruction', options); + helper.ensureFlagExists('ignoreAttributes', options); + helper.ensureFlagExists('ignoreText', options); + helper.ensureFlagExists('ignoreComment', options); + helper.ensureFlagExists('ignoreCdata', options); + helper.ensureFlagExists('ignoreDoctype', options); + helper.ensureFlagExists('compact', options); + helper.ensureFlagExists('indentText', options); + helper.ensureFlagExists('indentCdata', options); + helper.ensureFlagExists('indentAttributes', options); + helper.ensureFlagExists('indentInstruction', options); + helper.ensureFlagExists('fullTagEmptyElement', options); + helper.ensureFlagExists('noQuotesForNativeAttributes', options); + helper.ensureSpacesExists(options); if (typeof options.spaces === 'number') { options.spaces = Array(options.spaces + 1).join(' '); } - common.ensureKeyExists('declaration', options); - common.ensureKeyExists('instruction', options); - common.ensureKeyExists('attributes', options); - common.ensureKeyExists('text', options); - common.ensureKeyExists('comment', options); - common.ensureKeyExists('cdata', options); - common.ensureKeyExists('doctype', options); - common.ensureKeyExists('type', options); - common.ensureKeyExists('name', options); - common.ensureKeyExists('elements', options); + helper.ensureKeyExists('declaration', options); + helper.ensureKeyExists('instruction', options); + helper.ensureKeyExists('attributes', options); + helper.ensureKeyExists('text', options); + helper.ensureKeyExists('comment', options); + helper.ensureKeyExists('cdata', options); + helper.ensureKeyExists('doctype', options); + helper.ensureKeyExists('type', options); + helper.ensureKeyExists('name', options); + helper.ensureKeyExists('elements', options); return options; } @@ -100,27 +100,27 @@ function hasContent(element, options) { if (element.elements && element.elements.length) { for (i = 0; i < element.elements.length; ++i) { switch (element.elements[i][options.typeKey]) { - case 'text': - if (options.indentText) { - return true; - } - break; // skip to next key - case 'cdata': - if (options.indentCdata) { - return true; - } - break; // skip to next key - case 'instruction': - if (options.indentInstruction) { - return true; - } - break; // skip to next key - case 'doctype': - case 'comment': - case 'element': + case 'text': + if (options.indentText) { return true; - default: + } + break; // skip to next key + case 'cdata': + if (options.indentCdata) { return true; + } + break; // skip to next key + case 'instruction': + if (options.indentInstruction) { + return true; + } + break; // skip to next key + case 'doctype': + case 'comment': + case 'element': + return true; + default: + return true; } } } @@ -150,15 +150,15 @@ function writeElements(elements, options, depth, firstLine) { return elements.reduce(function (xml, element) { var indent = writeIndentation(options, depth, firstLine && !xml); switch (element.type) { - case 'element': return xml + indent + writeElement(element, options, depth); - case 'comment': return xml + indent + writeComment(element[options.commentKey], options); - case 'doctype': return xml + indent + writeDoctype(element[options.doctypeKey], options); - case 'cdata': return xml + (options.indentCdata ? indent : '') + writeCdata(element[options.cdataKey], options); - case 'text': return xml + (options.indentText ? indent : '') + writeText(element[options.textKey], options); - case 'instruction': - var instruction = {}; - instruction[element[options.nameKey]] = element[options.attributesKey] ? element : element[options.instructionKey]; - return xml + (options.indentInstruction ? indent : '') + writeInstruction(instruction, options, depth); + case 'element': return xml + indent + writeElement(element, options, depth); + case 'comment': return xml + indent + writeComment(element[options.commentKey], options); + case 'doctype': return xml + indent + writeDoctype(element[options.doctypeKey], options); + case 'cdata': return xml + (options.indentCdata ? indent : '') + writeCdata(element[options.cdataKey], options); + case 'text': return xml + (options.indentText ? indent : '') + writeText(element[options.textKey], options); + case 'instruction': + var instruction = {}; + instruction[element[options.nameKey]] = element[options.attributesKey] ? element : element[options.instructionKey]; + return xml + (options.indentInstruction ? indent : '') + writeInstruction(instruction, options, depth); } }, ''); } @@ -168,29 +168,29 @@ function hasContentCompact(element, options, anyContent) { for (key in element) { if (element.hasOwnProperty(key)) { switch (key) { - case options.parentKey: - case options.attributesKey: - break; // skip to next key - case options.textKey: - if (options.indentText || anyContent) { - return true; - } - break; // skip to next key - case options.cdataKey: - if (options.indentCdata || anyContent) { - return true; - } - break; // skip to next key - case options.instructionKey: - if (options.indentInstruction || anyContent) { - return true; - } - break; // skip to next key - case options.doctypeKey: - case options.commentKey: + case options.parentKey: + case options.attributesKey: + break; // skip to next key + case options.textKey: + if (options.indentText || anyContent) { return true; - default: + } + break; // skip to next key + case options.cdataKey: + if (options.indentCdata || anyContent) { return true; + } + break; // skip to next key + case options.instructionKey: + if (options.indentInstruction || anyContent) { + return true; + } + break; // skip to next key + case options.doctypeKey: + case options.commentKey: + return true; + default: + return true; } } } @@ -232,14 +232,14 @@ function writeElementsCompact(element, options, depth, firstLine) { nodes = element[key] instanceof Array ? element[key] : [element[key]]; for (i = 0; i < nodes.length; ++i) { switch (key) { - case options.declarationKey: xml += writeDeclaration(nodes[i], options, depth); break; - case options.instructionKey: xml += (options.indentInstruction ? writeIndentation(options, depth, firstLine) : '') + writeInstruction(nodes[i], options, depth); break; - case options.attributesKey: case options.parentKey: break; // skip - case options.textKey: xml += (options.indentText ? writeIndentation(options, depth, firstLine) : '') + writeText(nodes[i], options); break; - case options.cdataKey: xml += (options.indentCdata ? writeIndentation(options, depth, firstLine) : '') + writeCdata(nodes[i], options); break; - case options.doctypeKey: xml += writeIndentation(options, depth, firstLine) + writeDoctype(nodes[i], options); break; - case options.commentKey: xml += writeIndentation(options, depth, firstLine) + writeComment(nodes[i], options); break; - default: xml += writeIndentation(options, depth, firstLine) + writeElementCompact(nodes[i], key, options, depth, hasContentCompact(nodes[i], options)); + case options.declarationKey: xml += writeDeclaration(nodes[i], options, depth); break; + case options.instructionKey: xml += (options.indentInstruction ? writeIndentation(options, depth, firstLine) : '') + writeInstruction(nodes[i], options, depth); break; + case options.attributesKey: case options.parentKey: break; // skip + case options.textKey: xml += (options.indentText ? writeIndentation(options, depth, firstLine) : '') + writeText(nodes[i], options); break; + case options.cdataKey: xml += (options.indentCdata ? writeIndentation(options, depth, firstLine) : '') + writeCdata(nodes[i], options); break; + case options.doctypeKey: xml += writeIndentation(options, depth, firstLine) + writeDoctype(nodes[i], options); break; + case options.commentKey: xml += writeIndentation(options, depth, firstLine) + writeComment(nodes[i], options); break; + default: xml += writeIndentation(options, depth, firstLine) + writeElementCompact(nodes[i], key, options, depth, hasContentCompact(nodes[i], options)); } firstLine = firstLine && !xml; } @@ -249,7 +249,6 @@ function writeElementsCompact(element, options, depth, firstLine) { } module.exports = function (js, options) { - 'use strict'; options = validateOptions(options); var xml = ''; if (options.compact) { diff --git a/lib/json2xml.js b/lib/json2xml.js index 400b801..6decaee 100644 --- a/lib/json2xml.js +++ b/lib/json2xml.js @@ -1,7 +1,6 @@ var js2xml = require('./js2xml.js'); module.exports = function (json, options) { - 'use strict'; if (json instanceof Buffer) { json = json.toString(); } @@ -10,7 +9,7 @@ module.exports = function (json, options) { try { js = JSON.parse(json); } catch (e) { - throw new Error("The JSON structure is invalid"); + throw new Error('The JSON structure is invalid'); } } else { js = json; diff --git a/lib/options-helper.js b/lib/options-helper.js new file mode 100644 index 0000000..bdbe2ef --- /dev/null +++ b/lib/options-helper.js @@ -0,0 +1,35 @@ +module.exports = { + + copyOptions: function (options) { + var key, copy = {}; + for (key in options) { + if (options.hasOwnProperty(key)) { + copy[key] = options[key]; + } + } + return copy; + }, + + ensureFlagExists: function (item, options) { + if (!(item in options) || typeof options[item] !== 'boolean') { + options[item] = false; + } + }, + + ensureSpacesExists: function (options) { + if (!('spaces' in options) || (typeof options.spaces !== 'number' && typeof options.spaces !== 'string')) { + options.spaces = 0; + } + }, + + ensureKeyExists: function (key, options) { + if (!(key + 'Key' in options) || typeof options[key + 'Key'] !== 'string') { + options[key + 'Key'] = options.compact ? '_' + key : key; + } + }, + + checkFnExists: function (key, options) { + return key + 'Fn' in options; + } + +}; diff --git a/lib/xml2js.js b/lib/xml2js.js index 2b80f80..4ce7cdf 100644 --- a/lib/xml2js.js +++ b/lib/xml2js.js @@ -1,40 +1,40 @@ var sax = require('sax'); var expat /*= require('node-expat');*/ = { on: function () { }, parse: function () { } }; -var common = require('./common'); +var helper = require('./options-helper'); var options; var pureJsParser = true; var currentElement; function validateOptions(userOptions) { - options = common.copyOptions(userOptions); - common.ensureFlagExists('ignoreDeclaration', options); - common.ensureFlagExists('ignoreInstruction', options); - common.ensureFlagExists('ignoreAttributes', options); - common.ensureFlagExists('ignoreText', options); - common.ensureFlagExists('ignoreComment', options); - common.ensureFlagExists('ignoreCdata', options); - common.ensureFlagExists('ignoreDoctype', options); - common.ensureFlagExists('compact', options); - common.ensureFlagExists('alwaysArray', options); - common.ensureFlagExists('alwaysChildren', options); - common.ensureFlagExists('addParent', options); - common.ensureFlagExists('trim', options); - common.ensureFlagExists('nativeType', options); - common.ensureFlagExists('sanitize', options); - common.ensureFlagExists('instructionHasAttributes', options); - common.ensureFlagExists('captureSpacesBetweenElements', options); - common.ensureKeyExists('declaration', options); - common.ensureKeyExists('instruction', options); - common.ensureKeyExists('attributes', options); - common.ensureKeyExists('text', options); - common.ensureKeyExists('comment', options); - common.ensureKeyExists('cdata', options); - common.ensureKeyExists('doctype', options); - common.ensureKeyExists('type', options); - common.ensureKeyExists('name', options); - common.ensureKeyExists('elements', options); - common.ensureKeyExists('parent', options); + options = helper.copyOptions(userOptions); + helper.ensureFlagExists('ignoreDeclaration', options); + helper.ensureFlagExists('ignoreInstruction', options); + helper.ensureFlagExists('ignoreAttributes', options); + helper.ensureFlagExists('ignoreText', options); + helper.ensureFlagExists('ignoreComment', options); + helper.ensureFlagExists('ignoreCdata', options); + helper.ensureFlagExists('ignoreDoctype', options); + helper.ensureFlagExists('compact', options); + helper.ensureFlagExists('alwaysArray', options); + helper.ensureFlagExists('alwaysChildren', options); + helper.ensureFlagExists('addParent', options); + helper.ensureFlagExists('trim', options); + helper.ensureFlagExists('nativeType', options); + helper.ensureFlagExists('sanitize', options); + helper.ensureFlagExists('instructionHasAttributes', options); + helper.ensureFlagExists('captureSpacesBetweenElements', options); + helper.ensureKeyExists('declaration', options); + helper.ensureKeyExists('instruction', options); + helper.ensureKeyExists('attributes', options); + helper.ensureKeyExists('text', options); + helper.ensureKeyExists('comment', options); + helper.ensureKeyExists('cdata', options); + helper.ensureKeyExists('doctype', options); + helper.ensureKeyExists('type', options); + helper.ensureKeyExists('name', options); + helper.ensureKeyExists('elements', options); + helper.ensureKeyExists('parent', options); return options; } diff --git a/lib/xml2json.js b/lib/xml2json.js index e3ad7ae..8fde51c 100644 --- a/lib/xml2json.js +++ b/lib/xml2json.js @@ -1,14 +1,13 @@ -var common = require('./common'); +var helper = require('./options-helper'); var xml2js = require('./xml2js'); function validateOptions (userOptions) { - var options = common.copyOptions(userOptions); - common.ensureSpacesExists(options); + var options = helper.copyOptions(userOptions); + helper.ensureSpacesExists(options); return options; } module.exports = function(xml, userOptions) { - 'use strict'; var options, js, json, parentKey; options = validateOptions(userOptions); js = xml2js(xml, options); diff --git a/package-lock.json b/package-lock.json index 78fae4b..7b0fe95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11161,9 +11161,9 @@ "dev": true }, "eslint": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.13.0.tgz", - "integrity": "sha512-1l2aVrEz9yiWsEQdL3XZEzTovHQJFZaTeIhOOilKQRiYNn1dVALoYOtn06iPoxhEwFukBPX4Ff8WoGD4r/7D2A==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.13.1.tgz", + "integrity": "sha512-UCJVV50RtLHYzBp1DZ8CMPtRSg4iVZvjgO9IJHIKyWU/AnJVjtdRikoUPLB29n5pzMB7TnsLQWf0V6VUJfoPfw==", "dev": true, "requires": { "ajv": "5.5.1", diff --git a/package.json b/package.json index 81852d2..64d5c25 100644 --- a/package.json +++ b/package.json @@ -48,12 +48,14 @@ "jasmine": "jasmine JASMINE_CONFIG_PATH=./test/jasmine.json", "watch:jasmine": "watch \"npm run jasmine\" lib/ test/", "bundle:jasmine": "globify test/*_test.js --watch --verbose --list --outfile test/browse-jasmine/bundle.js", - "live:jasmine": "browser-sync start --port 9991 --server test/browse-jasmine/ --files test/browse-jasmine/ --no-open --no-ui --no-online", - "open:jasmine": "biased-opener --browser chrome http://localhost:9991", - "istanbul": "istanbul cover --dir test/browse-coverage -x test/browse-** test/index.js", + "live:jasmine": "browser-sync start --port 9999 --server test/browse-jasmine/ --files test/browse-jasmine/ --no-open --no-ui --no-online", + "open-help": "biased-opener --help", + "open:jasmine": "biased-opener --browser chrome http://localhost:9999", + "istanbul-original": "istanbul cover --dir test/browse-coverage -x test/browse-** test/index.js", + "istanbul": "istanbul cover --dir test/browse-coverage test/index.js", "watch:istanbul": "watch \"npm run istanbul\" lib/ test/ --ignoreDirectoryPattern=/browse-.+/", - "live:istanbul": "browser-sync start --port 9992 --server test/browse-coverage/lcov-report/ --files test/browse-coverage/lcov-report/ --no-open --no-ui --no-online", - "open:istanbul": "biased-opener --browser chrome http://localhost:9992", + "live:istanbul": "browser-sync start --port 9998 --server test/browse-coverage/lcov-report/ --files test/browse-coverage/lcov-report/ --no-open --no-ui --no-online", + "open:istanbul": "biased-opener --browser chrome http://localhost:9998", "live": "npm-run-all --parallel live:* open:*", "start": "npm-run-all --parallel bundle:jasmine watch:istanbul live:* open:*", "git:commit": "git add . && git commit -a -m \"Committed by npm script.\" && git push origin master", @@ -81,7 +83,7 @@ "codecov": "^3.0.0", "coveralls": "^3.0.0", "cross-env": "^5.1.1", - "eslint": "^4.13.0", + "eslint": "^4.13.1", "globify": "^2.2.1", "istanbul": "^0.4.5", "jasmine": "^2.8.0", diff --git a/test/browse-jasmine/bundle.js b/test/browse-jasmine/bundle.js index 3e986f3..9af3bef 100644 --- a/test/browse-jasmine/bundle.js +++ b/test/browse-jasmine/bundle.js @@ -1,9120 +1 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o/g, ">").replace(/"/g, """).replace(/'/g, "'"); - }, - copyOptions: function (options) { - var key, copy = {}; - for (key in options) { - if (options.hasOwnProperty(key)) { - copy[key] = options[key]; - } - } - return copy; - }, - ensureFlagExists: function (item, options) { - if (!(item in options) || typeof options[item] !== 'boolean') { - options[item] = false; - } - }, - ensureSpacesExists: function (options) { - if (!('spaces' in options) || (typeof options.spaces !== 'number' && typeof options.spaces !== 'string')) { - options.spaces = 0; - } - }, - ensureKeyExists: function (key, options) { - if (!(key + 'Key' in options) || typeof options[key + 'Key'] !== 'string') { - options[key + 'Key'] = options.compact ? '_' + key : key; - } - }, - getCommandLineHelp: function (command, requiredArgs, optionalArgs) { - var reqArgs = requiredArgs.reduce(function (res, arg) {return res + ' <' + arg.arg + '>';}, ''); - var output = 'Usage: ' + command + reqArgs + ' [options]' + '\n'; - requiredArgs.forEach(function (argument) { - output += ' <' + argument.arg + '>' + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n'; - }); - output += '\nOptions:' + '\n'; - optionalArgs.forEach(function (argument) { - output += ' --' + argument.arg + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n'; - }); - return output; - }, - mapCommandLineArgs: function (requiredArgs, optionalArgs) { - var options = {}, r, o, a = 2; - for (r = 0; r < requiredArgs.length; r += 1) { - if (a < process.argv.length && process.argv[a].substr(0, 1) !== '-' && process.argv[a] !== 'JASMINE_CONFIG_PATH=./jasmine.json') { - options[requiredArgs[r].option] = process.argv[a++]; - } else { - break; - } - } - for (; a < process.argv.length; a += 1) { - for (o = 0; o < optionalArgs.length; o += 1) { - if (optionalArgs[o].alias === process.argv[a].slice(1) || optionalArgs[o].arg === process.argv[a].slice(2)) { - break; - } - } - if (o < optionalArgs.length) { - switch (optionalArgs[o].type) { - case 'file': case 'string': case 'number': - if (a + 1 < process.argv.length) { - a += 1; - options[optionalArgs[o].option] = (optionalArgs[o].type === 'number' ? Number(process.argv[a]) : process.argv[a]); - } - break; - case 'flag': - options[optionalArgs[o].option] = true; break; - } - } - } - return options; - } -}; -}).call(this,require('_process')) -},{"_process":17}],2:[function(require,module,exports){ -/*jslint node:true */ - -var xml2js = require('./xml2js'); -var xml2json = require('./xml2json'); -var js2xml = require('./js2xml'); -var json2xml = require('./json2xml'); - -module.exports = { - xml2js: xml2js, - xml2json: xml2json, - js2xml: js2xml, - json2xml: json2xml -}; -},{"./js2xml":3,"./json2xml":4,"./xml2js":5,"./xml2json":6}],3:[function(require,module,exports){ -var common = require('./common'); - -function validateOptions(userOptions) { - var options = common.copyOptions(userOptions); - common.ensureFlagExists('ignoreDeclaration', options); - common.ensureFlagExists('ignoreInstruction', options); - common.ensureFlagExists('ignoreAttributes', options); - common.ensureFlagExists('ignoreText', options); - common.ensureFlagExists('ignoreComment', options); - common.ensureFlagExists('ignoreCdata', options); - common.ensureFlagExists('ignoreDoctype', options); - common.ensureFlagExists('compact', options); - common.ensureFlagExists('indentText', options); - common.ensureFlagExists('indentCdata', options); - common.ensureFlagExists('indentInstruction', options); - common.ensureFlagExists('fullTagEmptyElement', options); - common.ensureSpacesExists(options); - if (typeof options.spaces === 'number') { - options.spaces = Array(options.spaces + 1).join(' '); - } - common.ensureKeyExists('declaration', options); - common.ensureKeyExists('instruction', options); - common.ensureKeyExists('attributes', options); - common.ensureKeyExists('text', options); - common.ensureKeyExists('comment', options); - common.ensureKeyExists('cdata', options); - common.ensureKeyExists('doctype', options); - common.ensureKeyExists('type', options); - common.ensureKeyExists('name', options); - common.ensureKeyExists('elements', options); - return options; -} - -function writeIndentation(options, depth, firstLine) { - return (!firstLine && options.spaces ? '\n' : '') + Array(depth + 1).join(options.spaces); -} - -function writeAttributes(attributes, options) { - if (options.ignoreAttributes) { - return ''; - } - var key, result = ''; - for (key in attributes) { - if (attributes.hasOwnProperty(key)) { - result += ' ' + key + '="' + attributes[key] + '"'; - } - } - return result; -} - -function writeDeclaration(declaration, options) { - return options.ignoreDeclaration ? '' : ''; -} - -function writeInstruction(instruction, options) { - if (options.ignoreInstruction) { - return ''; - } - var key; - for (key in instruction) { - if (instruction.hasOwnProperty(key)) { - break; - } - } - return ''; -} - -function writeComment(comment, options) { - return options.ignoreComment ? '' : ''; -} - -function writeCdata(cdata, options) { - return options.ignoreCdata ? '' : ''; -} - -function writeDoctype(doctype, options) { - return options.ignoreDoctype ? '' : ''; -} - -function writeText(text, options) { - return options.ignoreText ? '' : text.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); -} - -function hasContent(element, options) { - var i; - if (element.elements && element.elements.length) { - for (i = 0; i < element.elements.length; ++i) { - switch (element.elements[i][options.typeKey]) { - case 'text': - if (options.indentText) { - return true; - } - break; // skip to next key - case 'cdata': - if (options.indentCdata) { - return true; - } - break; // skip to next key - case 'instruction': - if (options.indentInstruction) { - return true; - } - break; // skip to next key - case 'doctype': - case 'comment': - case 'element': - return true; - default: - return true; - } - } - } - return false; -} - -function writeElement(element, options, depth) { - var xml = ''; - xml += '<' + element.name; - if (element[options.attributesKey]) { - xml += writeAttributes(element[options.attributesKey], options); - } - if (options.fullTagEmptyElement || (element[options.elementsKey] && element[options.elementsKey].length) || (element[options.attributesKey] && element[options.attributesKey]['xml:space'] === 'preserve')) { - xml += '>'; - if (element[options.elementsKey] && element[options.elementsKey].length) { - xml += writeElements(element[options.elementsKey], options, depth + 1); - } - xml += options.spaces && hasContent(element, options) ? '\n' + Array(depth + 1).join(options.spaces) : ''; - xml += ''; - } else { - xml += '/>'; - } - return xml; -} - -function writeElements(elements, options, depth, firstLine) { - return elements.reduce(function (xml, element) { - var indent = writeIndentation(options, depth, firstLine && !xml); - switch (element.type) { - case 'element': return xml + indent + writeElement(element, options, depth); - case 'comment': return xml + indent + writeComment(element[options.commentKey], options); - case 'doctype': return xml + indent + writeDoctype(element[options.doctypeKey], options); - case 'cdata': return xml + (options.indentCdata ? indent : '') + writeCdata(element[options.cdataKey], options); - case 'text': return xml + (options.indentText ? indent : '') + writeText(element[options.textKey], options); - case 'instruction': - var instruction = {}; - instruction[element[options.nameKey]] = element[options.instructionKey]; - return xml + (options.indentInstruction ? indent : '') + writeInstruction(instruction, options); - } - }, ''); -} - -function hasContentCompact(element, options, anyContent) { - var key; - for (key in element) { - if (element.hasOwnProperty(key)) { - switch (key) { - case options.parentKey: - case options.attributesKey: - break; // skip to next key - case options.textKey: - if (options.indentText || anyContent) { - return true; - } - break; // skip to next key - case options.cdataKey: - if (options.indentCdata || anyContent) { - return true; - } - break; // skip to next key - case options.instructionKey: - if (options.indentInstruction || anyContent) { - return true; - } - break; // skip to next key - case options.doctypeKey: - case options.commentKey: - return true; - default: - return true; - } - } - } - return false; -} - -function writeElementCompact(element, name, options, depth, indent) { - var xml = ''; - if (name) { - xml += '<' + name; - if (element[options.attributesKey]) { - xml += writeAttributes(element[options.attributesKey], options); - } - if (options.fullTagEmptyElement || hasContentCompact(element, options, true) || element[options.attributesKey] && element[options.attributesKey]['xml:space'] === 'preserve') { - xml += '>'; - } else { - xml += '/>'; - return xml; - } - } - xml += writeElementsCompact(element, options, depth + 1, false); - if (name) { - xml += (indent ? writeIndentation(options, depth, false) : '') + ''; - } - return xml; -} - -function writeElementsCompact(element, options, depth, firstLine) { - var i, key, nodes, xml = ''; - for (key in element) { - if (element.hasOwnProperty(key)) { - nodes = element[key] instanceof Array ? element[key] : [element[key]]; - for (i = 0; i < nodes.length; ++i) { - switch (key) { - case options.declarationKey: xml += writeDeclaration(nodes[i], options); break; - case options.instructionKey: xml += (options.indentInstruction ? writeIndentation(options, depth, firstLine) : '') + writeInstruction(nodes[i], options); break; - case options.attributesKey: case options.parentKey: break; // skip - case options.textKey: xml += (options.indentText ? writeIndentation(options, depth, firstLine) : '') + writeText(nodes[i], options); break; - case options.cdataKey: xml += (options.indentCdata ? writeIndentation(options, depth, firstLine) : '') + writeCdata(nodes[i], options); break; - case options.doctypeKey: xml += writeIndentation(options, depth, firstLine) + writeDoctype(nodes[i], options); break; - case options.commentKey: xml += writeIndentation(options, depth, firstLine) + writeComment(nodes[i], options); break; - default: xml += writeIndentation(options, depth, firstLine) + writeElementCompact(nodes[i], key, options, depth, hasContentCompact(nodes[i], options)); - } - firstLine = firstLine && !xml; - } - } - } - return xml; -} - -module.exports = function (js, options) { - 'use strict'; - options = validateOptions(options); - var xml = ''; - if (options.compact) { - xml = writeElementsCompact(js, options, 0, true); - } else { - if (js[options.declarationKey]) { - xml += writeDeclaration(js[options.declarationKey], options); - } - if (js[options.elementsKey] && js[options.elementsKey].length) { - xml += writeElements(js[options.elementsKey], options, 0, !xml); - } - } - return xml; -}; - -},{"./common":1}],4:[function(require,module,exports){ -(function (Buffer){ -var js2xml = require('./js2xml.js'); - -module.exports = function (json, options) { - 'use strict'; - if (json instanceof Buffer) { - json = json.toString(); - } - var js = null; - if (typeof (json) === 'string') { - try { - js = JSON.parse(json); - } catch (e) { - throw new Error("The JSON structure is invalid"); - } - } else { - js = json; - } - return js2xml(js, options); -}; -}).call(this,require("buffer").Buffer) -},{"./js2xml.js":3,"buffer":35}],5:[function(require,module,exports){ -var sax = require('sax'); -var expat /*= require('node-expat');*/ = { on: function () { }, parse: function () { } }; -var common = require('./common'); - -var options; -var pureJsParser = true; -var currentElement; - -function validateOptions(userOptions) { - options = common.copyOptions(userOptions); - common.ensureFlagExists('ignoreDeclaration', options); - common.ensureFlagExists('ignoreInstruction', options); - common.ensureFlagExists('ignoreAttributes', options); - common.ensureFlagExists('ignoreText', options); - common.ensureFlagExists('ignoreComment', options); - common.ensureFlagExists('ignoreCdata', options); - common.ensureFlagExists('ignoreDoctype', options); - common.ensureFlagExists('compact', options); - common.ensureFlagExists('alwaysArray', options); - common.ensureFlagExists('alwaysChildren', options); - common.ensureFlagExists('addParent', options); - common.ensureFlagExists('trim', options); - common.ensureFlagExists('nativeType', options); - common.ensureFlagExists('sanitize', options); - common.ensureKeyExists('declaration', options); - common.ensureKeyExists('instruction', options); - common.ensureKeyExists('attributes', options); - common.ensureKeyExists('text', options); - common.ensureKeyExists('comment', options); - common.ensureKeyExists('cdata', options); - common.ensureKeyExists('doctype', options); - common.ensureKeyExists('type', options); - common.ensureKeyExists('name', options); - common.ensureKeyExists('elements', options); - common.ensureKeyExists('parent', options); - return options; -} - -function nativeType(value) { - var nValue = Number(value); - if (!isNaN(nValue)) { - return nValue; - } - var bValue = value.toLowerCase(); - if (bValue === 'true') { - return true; - } else if (bValue === 'false') { - return false; - } - return value; -} - -function addField(type, value, options) { - if (options.compact) { - if (!currentElement[options[type + 'Key']] && options.alwaysArray) { - currentElement[options[type + 'Key']] = []; - } - if (currentElement[options[type + 'Key']] && !(currentElement[options[type + 'Key']] instanceof Array)) { - currentElement[options[type + 'Key']] = [currentElement[options[type + 'Key']]]; - } - if (currentElement[options[type + 'Key']] instanceof Array) { - currentElement[options[type + 'Key']].push(value); - } else { - currentElement[options[type + 'Key']] = value; - } - } else { - if (!currentElement[options.elementsKey]) { - currentElement[options.elementsKey] = []; - } - var key, element = {}; - element[options.typeKey] = type; - if (typeof value === 'object') { - for (key in value) { - if (value.hasOwnProperty(key)) { - element[options.nameKey] = key; - element[options[type + 'Key']] = value[key]; - break; - } - } - } else { - element[options[type + 'Key']] = value; - } - if (options.addParent) { - element[options.parentKey] = currentElement; - } - currentElement[options.elementsKey].push(element); - } -} - -function onInstruction(instruction) { - if (instruction.name.toLowerCase() === 'xml') { - if (options.ignoreDeclaration) { - return; - } - currentElement[options.declarationKey] = {}; - while (instruction.body) { - var attribute = instruction.body.match(/([\w:-]+)\s*=\s*"([^"]*)"|'([^']*)'|(\w+)\s*/); - if (!attribute) { - break; - } - if (!currentElement[options.declarationKey][options.attributesKey]) { - currentElement[options.declarationKey][options.attributesKey] = {}; - } - currentElement[options.declarationKey][options.attributesKey][attribute[1]] = attribute[2]; - instruction.body = instruction.body.slice(attribute[0].length); // advance the string - } - if (options.addParent) { - currentElement[options.declarationKey][options.parentKey] = currentElement; - } - } else { - if (options.ignoreInstruction) { - return; - } - if (options.trim) { - instruction.body = instruction.body.trim(); - } - if (options.sanitize) { - instruction.body = common.sanitize(instruction.body); - } - var value = {}; - value[instruction.name] = instruction.body; - addField('instruction', value, options); - } -} - -function onStartElement(name, attributes) { - var key, element; - if (typeof name === 'object') { - attributes = name.attributes; - name = name.name; - } - if (options.trim && attributes) { - for (key in attributes) { - if (attributes.hasOwnProperty(key)) { - attributes[key] = attributes[key].trim(); - } - } - } - if (options.compact) { - element = {}; - if (!options.ignoreAttributes && attributes && Object.keys(attributes).length) { - element[options.attributesKey] = {}; - for (key in attributes) { - if (attributes.hasOwnProperty(key)) { - element[options.attributesKey][key] = attributes[key]; - } - } - } - if (!(name in currentElement) && options.alwaysArray) { - currentElement[name] = []; - } - if (currentElement[name] && !(currentElement[name] instanceof Array)) { - currentElement[name] = [currentElement[name]]; - } - if (currentElement[name] instanceof Array) { - currentElement[name].push(element); - } else { - currentElement[name] = element; - } - } else { - if (!currentElement[options.elementsKey]) { - currentElement[options.elementsKey] = []; - } - element = {}; - element[options.typeKey] = 'element'; - element[options.nameKey] = name; - if (!options.ignoreAttributes && attributes && Object.keys(attributes).length) { - element[options.attributesKey] = attributes; - } - if (options.alwaysChildren) { - element[options.elementsKey] = []; - } - currentElement[options.elementsKey].push(element); - } - // if (options.addParent) { - element[options.parentKey] = currentElement; - // } - currentElement = element; -} - -function onText(text) { - if (options.ignoreText) { - return; - } - if (!text.trim()) { - return; - } - if (options.trim) { - text = text.trim(); - } - if (options.nativeType) { - text = nativeType(text); - } - if (options.sanitize) { - text = common.sanitize(text); - } - addField('text', text, options); -} - -function onComment(comment) { - if (options.ignoreComment) { - return; - } - if (options.trim) { - comment = comment.trim(); - } - if (options.sanitize) { - comment = common.sanitize(comment); - } - addField('comment', comment, options); -} - -function onEndElement(name) { - var parentElement = currentElement[options.parentKey]; - if (!options.addParent) { - delete currentElement[options.parentKey]; - } - currentElement = parentElement; -} - -function onCdata(cdata) { - if (options.ignoreCdata) { - return; - } - if (options.trim) { - cdata = cdata.trim(); - } - addField('cdata', cdata, options); -} - -function onDoctype(doctype) { - if (options.ignoreDoctype) { - return; - } - doctype = doctype.replace(/^ /, ''); - if (options.trim) { - doctype = doctype.trim(); - } - addField('doctype', doctype, options); -} - -function onError(error) { - error.note = error; //console.error(error); -} - -module.exports = function (xml, userOptions) { - - var parser = pureJsParser ? sax.parser(true, {}) : parser = new expat.Parser('UTF-8'); - var result = {}; - currentElement = result; - - options = validateOptions(userOptions); - - if (pureJsParser) { - parser.onopentag = onStartElement; - parser.ontext = onText; - parser.oncomment = onComment; - parser.onclosetag = onEndElement; - parser.onerror = onError; - parser.oncdata = onCdata; - parser.ondoctype = onDoctype; - parser.onprocessinginstruction = onInstruction; - } else { - parser.on('startElement', onStartElement); - parser.on('text', onText); - parser.on('comment', onComment); - parser.on('endElement', onEndElement); - parser.on('error', onError); - //parser.on('startCdata', onStartCdata); - //parser.on('endCdata', onEndCdata); - //parser.on('entityDecl', onEntityDecl); - } - - if (pureJsParser) { - parser.write(xml).close(); - } else { - if (!parser.parse(xml)) { - throw new Error('XML parsing error: ' + parser.getError()); - } - } - - if (result[options.elementsKey]) { - var temp = result[options.elementsKey]; - delete result[options.elementsKey]; - result[options.elementsKey] = temp; - delete result.text; - } - - return result; - -}; - -},{"./common":1,"sax":29}],6:[function(require,module,exports){ -var common = require('./common'); -var xml2js = require('./xml2js'); - -function validateOptions (userOptions) { - var options = common.copyOptions(userOptions); - common.ensureSpacesExists(options); - return options; -} - -module.exports = function(xml, userOptions) { - 'use strict'; - var options, js, json, parentKey; - options = validateOptions(userOptions); - js = xml2js(xml, options); - parentKey = 'compact' in options && options.compact ? '_parent' : 'parent'; - // parentKey = ptions.compact ? '_parent' : 'parent'; // consider this - if ('addParent' in options && options.addParent) { - json = JSON.stringify(js, function (k, v) { return k === parentKey? '_' : v; }, options.spaces); - } else { - json = JSON.stringify(js, null, options.spaces); - } - return json.replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029'); -}; - -},{"./common":1,"./xml2js":5}],7:[function(require,module,exports){ - -},{}],8:[function(require,module,exports){ -(function (global){ -'use strict'; - -var buffer = require('buffer'); -var Buffer = buffer.Buffer; -var SlowBuffer = buffer.SlowBuffer; -var MAX_LEN = buffer.kMaxLength || 2147483647; -exports.alloc = function alloc(size, fill, encoding) { - if (typeof Buffer.alloc === 'function') { - return Buffer.alloc(size, fill, encoding); - } - if (typeof encoding === 'number') { - throw new TypeError('encoding must not be number'); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size > MAX_LEN) { - throw new RangeError('size is too large'); - } - var enc = encoding; - var _fill = fill; - if (_fill === undefined) { - enc = undefined; - _fill = 0; - } - var buf = new Buffer(size); - if (typeof _fill === 'string') { - var fillBuf = new Buffer(_fill, enc); - var flen = fillBuf.length; - var i = -1; - while (++i < size) { - buf[i] = fillBuf[i % flen]; - } - } else { - buf.fill(_fill); - } - return buf; -} -exports.allocUnsafe = function allocUnsafe(size) { - if (typeof Buffer.allocUnsafe === 'function') { - return Buffer.allocUnsafe(size); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size > MAX_LEN) { - throw new RangeError('size is too large'); - } - return new Buffer(size); -} -exports.from = function from(value, encodingOrOffset, length) { - if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) { - return Buffer.from(value, encodingOrOffset, length); - } - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number'); - } - if (typeof value === 'string') { - return new Buffer(value, encodingOrOffset); - } - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - var offset = encodingOrOffset; - if (arguments.length === 1) { - return new Buffer(value); - } - if (typeof offset === 'undefined') { - offset = 0; - } - var len = length; - if (typeof len === 'undefined') { - len = value.byteLength - offset; - } - if (offset >= value.byteLength) { - throw new RangeError('\'offset\' is out of bounds'); - } - if (len > value.byteLength - offset) { - throw new RangeError('\'length\' is out of bounds'); - } - return new Buffer(value.slice(offset, offset + len)); - } - if (Buffer.isBuffer(value)) { - var out = new Buffer(value.length); - value.copy(out, 0, 0, value.length); - return out; - } - if (value) { - if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) { - return new Buffer(value); - } - if (value.type === 'Buffer' && Array.isArray(value.data)) { - return new Buffer(value.data); - } - } - - throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.'); -} -exports.allocUnsafeSlow = function allocUnsafeSlow(size) { - if (typeof Buffer.allocUnsafeSlow === 'function') { - return Buffer.allocUnsafeSlow(size); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size >= MAX_LEN) { - throw new RangeError('size is too large'); - } - return new SlowBuffer(size); -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":35}],9:[function(require,module,exports){ -(function (Buffer){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. - -function isArray(arg) { - if (Array.isArray) { - return Array.isArray(arg); - } - return objectToString(arg) === '[object Array]'; -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -exports.isBuffer = Buffer.isBuffer; - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - -}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":13}],10:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); - err.context = er; - throw err; - } - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - args = Array.prototype.slice.call(arguments, 1); - handler.apply(this, args); - } - } else if (isObject(handler)) { - args = Array.prototype.slice.call(arguments, 1); - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.prototype.listenerCount = function(type) { - if (this._events) { - var evlistener = this._events[type]; - - if (isFunction(evlistener)) - return 1; - else if (evlistener) - return evlistener.length; - } - return 0; -}; - -EventEmitter.listenerCount = function(emitter, type) { - return emitter.listenerCount(type); -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],11:[function(require,module,exports){ -exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] - - i += d - - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} - - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} - - if (e === 0) { - e = 1 - eBias - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity) - } else { - m = m + Math.pow(2, mLen) - e = e - eBias - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen) -} - -exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 - - value = Math.abs(value) - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 - e = eMax - } else { - e = Math.floor(Math.log(value) / Math.LN2) - if (value * (c = Math.pow(2, -e)) < 1) { - e-- - c *= 2 - } - if (e + eBias >= 1) { - value += rt / c - } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } - - if (e + eBias >= eMax) { - m = 0 - e = eMax - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen) - e = e + eBias - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) - e = 0 - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} - - buffer[offset + i - d] |= s * 128 -} - -},{}],12:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],13:[function(require,module,exports){ -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} - -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} - -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} - -},{}],14:[function(require,module,exports){ -var toString = {}.toString; - -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; -}; - -},{}],15:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -// Split a filename into [root, dir, basename, ext], unix version -// 'root' is just a slash, or nothing. -var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; -var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); -}; - -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; - -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isAbsolute ? '/' : '') + path; -}; - -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; - -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); -}; - - -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); -}; - -exports.sep = '/'; -exports.delimiter = ':'; - -exports.dirname = function(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; -}; - - -exports.basename = function(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - - -exports.extname = function(path) { - return splitPath(path)[3]; -}; - -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; - -}).call(this,require('_process')) -},{"_process":17}],16:[function(require,module,exports){ -(function (process){ -'use strict'; - -if (!process.version || - process.version.indexOf('v0.') === 0 || - process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { - module.exports = nextTick; -} else { - module.exports = process.nextTick; -} - -function nextTick(fn, arg1, arg2, arg3) { - if (typeof fn !== 'function') { - throw new TypeError('"callback" argument must be a function'); - } - var len = arguments.length; - var args, i; - switch (len) { - case 0: - case 1: - return process.nextTick(fn); - case 2: - return process.nextTick(function afterTickOne() { - fn.call(null, arg1); - }); - case 3: - return process.nextTick(function afterTickTwo() { - fn.call(null, arg1, arg2); - }); - case 4: - return process.nextTick(function afterTickThree() { - fn.call(null, arg1, arg2, arg3); - }); - default: - args = new Array(len - 1); - i = 0; - while (i < args.length) { - args[i++] = arguments[i]; - } - return process.nextTick(function afterTick() { - fn.apply(null, args); - }); - } -} - -}).call(this,require('_process')) -},{"_process":17}],17:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],18:[function(require,module,exports){ -module.exports = require("./lib/_stream_duplex.js") - -},{"./lib/_stream_duplex.js":19}],19:[function(require,module,exports){ -// a duplex stream is just a stream that is both readable and writable. -// Since JS doesn't have multiple prototypal inheritance, this class -// prototypally inherits from Readable, and then parasitically from -// Writable. - -'use strict'; - -/**/ - -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) { - keys.push(key); - }return keys; -}; -/**/ - -module.exports = Duplex; - -/**/ -var processNextTick = require('process-nextick-args'); -/**/ - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -var Readable = require('./_stream_readable'); -var Writable = require('./_stream_writable'); - -util.inherits(Duplex, Readable); - -var keys = objectKeys(Writable.prototype); -for (var v = 0; v < keys.length; v++) { - var method = keys[v]; - if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; -} - -function Duplex(options) { - if (!(this instanceof Duplex)) return new Duplex(options); - - Readable.call(this, options); - Writable.call(this, options); - - if (options && options.readable === false) this.readable = false; - - if (options && options.writable === false) this.writable = false; - - this.allowHalfOpen = true; - if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; - - this.once('end', onend); -} - -// the no-half-open enforcer -function onend() { - // if we allow half-open state, or if the writable side ended, - // then we're ok. - if (this.allowHalfOpen || this._writableState.ended) return; - - // no more data can be written. - // But allow more writes to happen in this tick. - processNextTick(onEndNT, this); -} - -function onEndNT(self) { - self.end(); -} - -function forEach(xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} -},{"./_stream_readable":21,"./_stream_writable":23,"core-util-is":9,"inherits":12,"process-nextick-args":16}],20:[function(require,module,exports){ -// a passthrough stream. -// basically just the most minimal sort of Transform stream. -// Every written chunk gets output as-is. - -'use strict'; - -module.exports = PassThrough; - -var Transform = require('./_stream_transform'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -util.inherits(PassThrough, Transform); - -function PassThrough(options) { - if (!(this instanceof PassThrough)) return new PassThrough(options); - - Transform.call(this, options); -} - -PassThrough.prototype._transform = function (chunk, encoding, cb) { - cb(null, chunk); -}; -},{"./_stream_transform":22,"core-util-is":9,"inherits":12}],21:[function(require,module,exports){ -(function (process){ -'use strict'; - -module.exports = Readable; - -/**/ -var processNextTick = require('process-nextick-args'); -/**/ - -/**/ -var isArray = require('isarray'); -/**/ - -/**/ -var Duplex; -/**/ - -Readable.ReadableState = ReadableState; - -/**/ -var EE = require('events').EventEmitter; - -var EElistenerCount = function (emitter, type) { - return emitter.listeners(type).length; -}; -/**/ - -/**/ -var Stream; -(function () { - try { - Stream = require('st' + 'ream'); - } catch (_) {} finally { - if (!Stream) Stream = require('events').EventEmitter; - } -})(); -/**/ - -var Buffer = require('buffer').Buffer; -/**/ -var bufferShim = require('buffer-shims'); -/**/ - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -/**/ -var debugUtil = require('util'); -var debug = void 0; -if (debugUtil && debugUtil.debuglog) { - debug = debugUtil.debuglog('stream'); -} else { - debug = function () {}; -} -/**/ - -var BufferList = require('./internal/streams/BufferList'); -var StringDecoder; - -util.inherits(Readable, Stream); - -function prependListener(emitter, event, fn) { - // Sadly this is not cacheable as some libraries bundle their own - // event emitter implementation with them. - if (typeof emitter.prependListener === 'function') { - return emitter.prependListener(event, fn); - } else { - // This is a hack to make sure that our error handler is attached before any - // userland ones. NEVER DO THIS. This is here only because this code needs - // to continue to work with older versions of Node.js that do not include - // the prependListener() method. The goal is to eventually remove this hack. - if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; - } -} - -function ReadableState(options, stream) { - Duplex = Duplex || require('./_stream_duplex'); - - options = options || {}; - - // object stream flag. Used to make read(n) ignore n and to - // make all the buffer merging and length checks go away - this.objectMode = !!options.objectMode; - - if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode; - - // the point at which it stops calling _read() to fill the buffer - // Note: 0 is a valid value, means "don't call _read preemptively ever" - var hwm = options.highWaterMark; - var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; - - // cast to ints. - this.highWaterMark = ~ ~this.highWaterMark; - - // A linked list is used to store data chunks instead of an array because the - // linked list can remove elements from the beginning faster than - // array.shift() - this.buffer = new BufferList(); - this.length = 0; - this.pipes = null; - this.pipesCount = 0; - this.flowing = null; - this.ended = false; - this.endEmitted = false; - this.reading = false; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - this.resumeScheduled = false; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // when piping, we only care about 'readable' events that happen - // after read()ing all the bytes and not getting any pushback. - this.ranOut = false; - - // the number of writers that are awaiting a drain event in .pipe()s - this.awaitDrain = 0; - - // if true, a maybeReadMore has been scheduled - this.readingMore = false; - - this.decoder = null; - this.encoding = null; - if (options.encoding) { - if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; - this.decoder = new StringDecoder(options.encoding); - this.encoding = options.encoding; - } -} - -function Readable(options) { - Duplex = Duplex || require('./_stream_duplex'); - - if (!(this instanceof Readable)) return new Readable(options); - - this._readableState = new ReadableState(options, this); - - // legacy - this.readable = true; - - if (options && typeof options.read === 'function') this._read = options.read; - - Stream.call(this); -} - -// Manually shove something into the read() buffer. -// This returns true if the highWaterMark has not been hit yet, -// similar to how Writable.write() returns true if you should -// write() some more. -Readable.prototype.push = function (chunk, encoding) { - var state = this._readableState; - - if (!state.objectMode && typeof chunk === 'string') { - encoding = encoding || state.defaultEncoding; - if (encoding !== state.encoding) { - chunk = bufferShim.from(chunk, encoding); - encoding = ''; - } - } - - return readableAddChunk(this, state, chunk, encoding, false); -}; - -// Unshift should *always* be something directly out of read() -Readable.prototype.unshift = function (chunk) { - var state = this._readableState; - return readableAddChunk(this, state, chunk, '', true); -}; - -Readable.prototype.isPaused = function () { - return this._readableState.flowing === false; -}; - -function readableAddChunk(stream, state, chunk, encoding, addToFront) { - var er = chunkInvalid(state, chunk); - if (er) { - stream.emit('error', er); - } else if (chunk === null) { - state.reading = false; - onEofChunk(stream, state); - } else if (state.objectMode || chunk && chunk.length > 0) { - if (state.ended && !addToFront) { - var e = new Error('stream.push() after EOF'); - stream.emit('error', e); - } else if (state.endEmitted && addToFront) { - var _e = new Error('stream.unshift() after end event'); - stream.emit('error', _e); - } else { - var skipAdd; - if (state.decoder && !addToFront && !encoding) { - chunk = state.decoder.write(chunk); - skipAdd = !state.objectMode && chunk.length === 0; - } - - if (!addToFront) state.reading = false; - - // Don't add to the buffer if we've decoded to an empty string chunk and - // we're not in object mode - if (!skipAdd) { - // if we want the data now, just emit it. - if (state.flowing && state.length === 0 && !state.sync) { - stream.emit('data', chunk); - stream.read(0); - } else { - // update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); - - if (state.needReadable) emitReadable(stream); - } - } - - maybeReadMore(stream, state); - } - } else if (!addToFront) { - state.reading = false; - } - - return needMoreData(state); -} - -// if it's past the high water mark, we can push in some more. -// Also, if we have no data yet, we can stand some -// more bytes. This is to work around cases where hwm=0, -// such as the repl. Also, if the push() triggered a -// readable event, and the user called read(largeNumber) such that -// needReadable was set, then we ought to push more, so that another -// 'readable' event will be triggered. -function needMoreData(state) { - return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); -} - -// backwards compatibility. -Readable.prototype.setEncoding = function (enc) { - if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; - this._readableState.decoder = new StringDecoder(enc); - this._readableState.encoding = enc; - return this; -}; - -// Don't raise the hwm > 8MB -var MAX_HWM = 0x800000; -function computeNewHighWaterMark(n) { - if (n >= MAX_HWM) { - n = MAX_HWM; - } else { - // Get the next highest power of 2 to prevent increasing hwm excessively in - // tiny amounts - n--; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; - n++; - } - return n; -} - -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function howMuchToRead(n, state) { - if (n <= 0 || state.length === 0 && state.ended) return 0; - if (state.objectMode) return 1; - if (n !== n) { - // Only flow one buffer at a time - if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; - } - // If we're asking for more than the current hwm, then raise the hwm. - if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); - if (n <= state.length) return n; - // Don't have enough - if (!state.ended) { - state.needReadable = true; - return 0; - } - return state.length; -} - -// you can override either this method, or the async _read(n) below. -Readable.prototype.read = function (n) { - debug('read', n); - n = parseInt(n, 10); - var state = this._readableState; - var nOrig = n; - - if (n !== 0) state.emittedReadable = false; - - // if we're doing read(0) to trigger a readable event, but we - // already have a bunch of data in the buffer, then just trigger - // the 'readable' event and move on. - if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { - debug('read: emitReadable', state.length, state.ended); - if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); - return null; - } - - n = howMuchToRead(n, state); - - // if we've ended, and we're now clear, then finish it up. - if (n === 0 && state.ended) { - if (state.length === 0) endReadable(this); - return null; - } - - // All the actual chunk generation logic needs to be - // *below* the call to _read. The reason is that in certain - // synthetic stream cases, such as passthrough streams, _read - // may be a completely synchronous operation which may change - // the state of the read buffer, providing enough data when - // before there was *not* enough. - // - // So, the steps are: - // 1. Figure out what the state of things will be after we do - // a read from the buffer. - // - // 2. If that resulting state will trigger a _read, then call _read. - // Note that this may be asynchronous, or synchronous. Yes, it is - // deeply ugly to write APIs this way, but that still doesn't mean - // that the Readable class should behave improperly, as streams are - // designed to be sync/async agnostic. - // Take note if the _read call is sync or async (ie, if the read call - // has returned yet), so that we know whether or not it's safe to emit - // 'readable' etc. - // - // 3. Actually pull the requested chunks out of the buffer and return. - - // if we need a readable event, then we need to do some reading. - var doRead = state.needReadable; - debug('need readable', doRead); - - // if we currently have less than the highWaterMark, then also read some - if (state.length === 0 || state.length - n < state.highWaterMark) { - doRead = true; - debug('length less than watermark', doRead); - } - - // however, if we've ended, then there's no point, and if we're already - // reading, then it's unnecessary. - if (state.ended || state.reading) { - doRead = false; - debug('reading or ended', doRead); - } else if (doRead) { - debug('do read'); - state.reading = true; - state.sync = true; - // if the length is currently zero, then we *need* a readable event. - if (state.length === 0) state.needReadable = true; - // call internal read method - this._read(state.highWaterMark); - state.sync = false; - // If _read pushed data synchronously, then `reading` will be false, - // and we need to re-evaluate how much data we can return to the user. - if (!state.reading) n = howMuchToRead(nOrig, state); - } - - var ret; - if (n > 0) ret = fromList(n, state);else ret = null; - - if (ret === null) { - state.needReadable = true; - n = 0; - } else { - state.length -= n; - } - - if (state.length === 0) { - // If we have nothing in the buffer, then we want to know - // as soon as we *do* get something into the buffer. - if (!state.ended) state.needReadable = true; - - // If we tried to read() past the EOF, then emit end on the next tick. - if (nOrig !== n && state.ended) endReadable(this); - } - - if (ret !== null) this.emit('data', ret); - - return ret; -}; - -function chunkInvalid(state, chunk) { - var er = null; - if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) { - er = new TypeError('Invalid non-string/buffer chunk'); - } - return er; -} - -function onEofChunk(stream, state) { - if (state.ended) return; - if (state.decoder) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) { - state.buffer.push(chunk); - state.length += state.objectMode ? 1 : chunk.length; - } - } - state.ended = true; - - // emit 'readable' now to make sure it gets picked up. - emitReadable(stream); -} - -// Don't emit readable right away in sync mode, because this can trigger -// another read() call => stack overflow. This way, it might trigger -// a nextTick recursion warning, but that's not so bad. -function emitReadable(stream) { - var state = stream._readableState; - state.needReadable = false; - if (!state.emittedReadable) { - debug('emitReadable', state.flowing); - state.emittedReadable = true; - if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream); - } -} - -function emitReadable_(stream) { - debug('emit readable'); - stream.emit('readable'); - flow(stream); -} - -// at this point, the user has presumably seen the 'readable' event, -// and called read() to consume some data. that may have triggered -// in turn another _read(n) call, in which case reading = true if -// it's in progress. -// However, if we're not ended, or reading, and the length < hwm, -// then go ahead and try to read some more preemptively. -function maybeReadMore(stream, state) { - if (!state.readingMore) { - state.readingMore = true; - processNextTick(maybeReadMore_, stream, state); - } -} - -function maybeReadMore_(stream, state) { - var len = state.length; - while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { - debug('maybeReadMore read 0'); - stream.read(0); - if (len === state.length) - // didn't get any data, stop spinning. - break;else len = state.length; - } - state.readingMore = false; -} - -// abstract method. to be overridden in specific implementation classes. -// call cb(er, data) where data is <= n in length. -// for virtual (non-string, non-buffer) streams, "length" is somewhat -// arbitrary, and perhaps not very meaningful. -Readable.prototype._read = function (n) { - this.emit('error', new Error('_read() is not implemented')); -}; - -Readable.prototype.pipe = function (dest, pipeOpts) { - var src = this; - var state = this._readableState; - - switch (state.pipesCount) { - case 0: - state.pipes = dest; - break; - case 1: - state.pipes = [state.pipes, dest]; - break; - default: - state.pipes.push(dest); - break; - } - state.pipesCount += 1; - debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); - - var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; - - var endFn = doEnd ? onend : cleanup; - if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn); - - dest.on('unpipe', onunpipe); - function onunpipe(readable) { - debug('onunpipe'); - if (readable === src) { - cleanup(); - } - } - - function onend() { - debug('onend'); - dest.end(); - } - - // when the dest drains, it reduces the awaitDrain counter - // on the source. This would be more elegant with a .once() - // handler in flow(), but adding and removing repeatedly is - // too slow. - var ondrain = pipeOnDrain(src); - dest.on('drain', ondrain); - - var cleanedUp = false; - function cleanup() { - debug('cleanup'); - // cleanup event handlers once the pipe is broken - dest.removeListener('close', onclose); - dest.removeListener('finish', onfinish); - dest.removeListener('drain', ondrain); - dest.removeListener('error', onerror); - dest.removeListener('unpipe', onunpipe); - src.removeListener('end', onend); - src.removeListener('end', cleanup); - src.removeListener('data', ondata); - - cleanedUp = true; - - // if the reader is waiting for a drain event from this - // specific writer, then it would cause it to never start - // flowing again. - // So, if this is awaiting a drain, then we just call it now. - // If we don't know, then assume that we are waiting for one. - if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); - } - - // If the user pushes more data while we're writing to dest then we'll end up - // in ondata again. However, we only want to increase awaitDrain once because - // dest will only emit one 'drain' event for the multiple writes. - // => Introduce a guard on increasing awaitDrain. - var increasedAwaitDrain = false; - src.on('data', ondata); - function ondata(chunk) { - debug('ondata'); - increasedAwaitDrain = false; - var ret = dest.write(chunk); - if (false === ret && !increasedAwaitDrain) { - // If the user unpiped during `dest.write()`, it is possible - // to get stuck in a permanently paused state if that write - // also returned false. - // => Check whether `dest` is still a piping destination. - if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { - debug('false write response, pause', src._readableState.awaitDrain); - src._readableState.awaitDrain++; - increasedAwaitDrain = true; - } - src.pause(); - } - } - - // if the dest has an error, then stop piping into it. - // however, don't suppress the throwing behavior for this. - function onerror(er) { - debug('onerror', er); - unpipe(); - dest.removeListener('error', onerror); - if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); - } - - // Make sure our error handler is attached before userland ones. - prependListener(dest, 'error', onerror); - - // Both close and finish should trigger unpipe, but only once. - function onclose() { - dest.removeListener('finish', onfinish); - unpipe(); - } - dest.once('close', onclose); - function onfinish() { - debug('onfinish'); - dest.removeListener('close', onclose); - unpipe(); - } - dest.once('finish', onfinish); - - function unpipe() { - debug('unpipe'); - src.unpipe(dest); - } - - // tell the dest that it's being piped to - dest.emit('pipe', src); - - // start the flow if it hasn't been started already. - if (!state.flowing) { - debug('pipe resume'); - src.resume(); - } - - return dest; -}; - -function pipeOnDrain(src) { - return function () { - var state = src._readableState; - debug('pipeOnDrain', state.awaitDrain); - if (state.awaitDrain) state.awaitDrain--; - if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { - state.flowing = true; - flow(src); - } - }; -} - -Readable.prototype.unpipe = function (dest) { - var state = this._readableState; - - // if we're not piping anywhere, then do nothing. - if (state.pipesCount === 0) return this; - - // just one destination. most common case. - if (state.pipesCount === 1) { - // passed in one, but it's not the right one. - if (dest && dest !== state.pipes) return this; - - if (!dest) dest = state.pipes; - - // got a match. - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; - if (dest) dest.emit('unpipe', this); - return this; - } - - // slow case. multiple pipe destinations. - - if (!dest) { - // remove all. - var dests = state.pipes; - var len = state.pipesCount; - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; - - for (var i = 0; i < len; i++) { - dests[i].emit('unpipe', this); - }return this; - } - - // try to find the right one. - var index = indexOf(state.pipes, dest); - if (index === -1) return this; - - state.pipes.splice(index, 1); - state.pipesCount -= 1; - if (state.pipesCount === 1) state.pipes = state.pipes[0]; - - dest.emit('unpipe', this); - - return this; -}; - -// set up data events if they are asked for -// Ensure readable listeners eventually get something -Readable.prototype.on = function (ev, fn) { - var res = Stream.prototype.on.call(this, ev, fn); - - if (ev === 'data') { - // Start flowing on next tick if stream isn't explicitly paused - if (this._readableState.flowing !== false) this.resume(); - } else if (ev === 'readable') { - var state = this._readableState; - if (!state.endEmitted && !state.readableListening) { - state.readableListening = state.needReadable = true; - state.emittedReadable = false; - if (!state.reading) { - processNextTick(nReadingNextTick, this); - } else if (state.length) { - emitReadable(this, state); - } - } - } - - return res; -}; -Readable.prototype.addListener = Readable.prototype.on; - -function nReadingNextTick(self) { - debug('readable nexttick read 0'); - self.read(0); -} - -// pause() and resume() are remnants of the legacy readable stream API -// If the user uses them, then switch into old mode. -Readable.prototype.resume = function () { - var state = this._readableState; - if (!state.flowing) { - debug('resume'); - state.flowing = true; - resume(this, state); - } - return this; -}; - -function resume(stream, state) { - if (!state.resumeScheduled) { - state.resumeScheduled = true; - processNextTick(resume_, stream, state); - } -} - -function resume_(stream, state) { - if (!state.reading) { - debug('resume read 0'); - stream.read(0); - } - - state.resumeScheduled = false; - state.awaitDrain = 0; - stream.emit('resume'); - flow(stream); - if (state.flowing && !state.reading) stream.read(0); -} - -Readable.prototype.pause = function () { - debug('call pause flowing=%j', this._readableState.flowing); - if (false !== this._readableState.flowing) { - debug('pause'); - this._readableState.flowing = false; - this.emit('pause'); - } - return this; -}; - -function flow(stream) { - var state = stream._readableState; - debug('flow', state.flowing); - while (state.flowing && stream.read() !== null) {} -} - -// wrap an old-style stream as the async data source. -// This is *not* part of the readable stream interface. -// It is an ugly unfortunate mess of history. -Readable.prototype.wrap = function (stream) { - var state = this._readableState; - var paused = false; - - var self = this; - stream.on('end', function () { - debug('wrapped end'); - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) self.push(chunk); - } - - self.push(null); - }); - - stream.on('data', function (chunk) { - debug('wrapped data'); - if (state.decoder) chunk = state.decoder.write(chunk); - - // don't skip over falsy values in objectMode - if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; - - var ret = self.push(chunk); - if (!ret) { - paused = true; - stream.pause(); - } - }); - - // proxy all the other methods. - // important when wrapping filters and duplexes. - for (var i in stream) { - if (this[i] === undefined && typeof stream[i] === 'function') { - this[i] = function (method) { - return function () { - return stream[method].apply(stream, arguments); - }; - }(i); - } - } - - // proxy certain important events. - var events = ['error', 'close', 'destroy', 'pause', 'resume']; - forEach(events, function (ev) { - stream.on(ev, self.emit.bind(self, ev)); - }); - - // when we try to consume some more bytes, simply unpause the - // underlying stream. - self._read = function (n) { - debug('wrapped _read', n); - if (paused) { - paused = false; - stream.resume(); - } - }; - - return self; -}; - -// exposed for testing purposes only. -Readable._fromList = fromList; - -// Pluck off n bytes from an array of buffers. -// Length is the combined lengths of all the buffers in the list. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function fromList(n, state) { - // nothing buffered - if (state.length === 0) return null; - - var ret; - if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { - // read it all, truncate the list - if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); - state.buffer.clear(); - } else { - // read part of list - ret = fromListPartial(n, state.buffer, state.decoder); - } - - return ret; -} - -// Extracts only enough buffered data to satisfy the amount requested. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function fromListPartial(n, list, hasStrings) { - var ret; - if (n < list.head.data.length) { - // slice is the same for buffers and strings - ret = list.head.data.slice(0, n); - list.head.data = list.head.data.slice(n); - } else if (n === list.head.data.length) { - // first chunk is a perfect match - ret = list.shift(); - } else { - // result spans more than one buffer - ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); - } - return ret; -} - -// Copies a specified amount of characters from the list of buffered data -// chunks. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function copyFromBufferString(n, list) { - var p = list.head; - var c = 1; - var ret = p.data; - n -= ret.length; - while (p = p.next) { - var str = p.data; - var nb = n > str.length ? str.length : n; - if (nb === str.length) ret += str;else ret += str.slice(0, n); - n -= nb; - if (n === 0) { - if (nb === str.length) { - ++c; - if (p.next) list.head = p.next;else list.head = list.tail = null; - } else { - list.head = p; - p.data = str.slice(nb); - } - break; - } - ++c; - } - list.length -= c; - return ret; -} - -// Copies a specified amount of bytes from the list of buffered data chunks. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function copyFromBuffer(n, list) { - var ret = bufferShim.allocUnsafe(n); - var p = list.head; - var c = 1; - p.data.copy(ret); - n -= p.data.length; - while (p = p.next) { - var buf = p.data; - var nb = n > buf.length ? buf.length : n; - buf.copy(ret, ret.length - n, 0, nb); - n -= nb; - if (n === 0) { - if (nb === buf.length) { - ++c; - if (p.next) list.head = p.next;else list.head = list.tail = null; - } else { - list.head = p; - p.data = buf.slice(nb); - } - break; - } - ++c; - } - list.length -= c; - return ret; -} - -function endReadable(stream) { - var state = stream._readableState; - - // If we get here before consuming all the bytes, then that is a - // bug in node. Should never happen. - if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); - - if (!state.endEmitted) { - state.ended = true; - processNextTick(endReadableNT, state, stream); - } -} - -function endReadableNT(state, stream) { - // Check that we didn't get one last unshift. - if (!state.endEmitted && state.length === 0) { - state.endEmitted = true; - stream.readable = false; - stream.emit('end'); - } -} - -function forEach(xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} - -function indexOf(xs, x) { - for (var i = 0, l = xs.length; i < l; i++) { - if (xs[i] === x) return i; - } - return -1; -} -}).call(this,require('_process')) -},{"./_stream_duplex":19,"./internal/streams/BufferList":24,"_process":17,"buffer":35,"buffer-shims":8,"core-util-is":9,"events":10,"inherits":12,"isarray":14,"process-nextick-args":16,"string_decoder/":31,"util":7}],22:[function(require,module,exports){ -// a transform stream is a readable/writable stream where you do -// something with the data. Sometimes it's called a "filter", -// but that's not a great name for it, since that implies a thing where -// some bits pass through, and others are simply ignored. (That would -// be a valid example of a transform, of course.) -// -// While the output is causally related to the input, it's not a -// necessarily symmetric or synchronous transformation. For example, -// a zlib stream might take multiple plain-text writes(), and then -// emit a single compressed chunk some time in the future. -// -// Here's how this works: -// -// The Transform stream has all the aspects of the readable and writable -// stream classes. When you write(chunk), that calls _write(chunk,cb) -// internally, and returns false if there's a lot of pending writes -// buffered up. When you call read(), that calls _read(n) until -// there's enough pending readable data buffered up. -// -// In a transform stream, the written data is placed in a buffer. When -// _read(n) is called, it transforms the queued up data, calling the -// buffered _write cb's as it consumes chunks. If consuming a single -// written chunk would result in multiple output chunks, then the first -// outputted bit calls the readcb, and subsequent chunks just go into -// the read buffer, and will cause it to emit 'readable' if necessary. -// -// This way, back-pressure is actually determined by the reading side, -// since _read has to be called to start processing a new chunk. However, -// a pathological inflate type of transform can cause excessive buffering -// here. For example, imagine a stream where every byte of input is -// interpreted as an integer from 0-255, and then results in that many -// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in -// 1kb of data being output. In this case, you could write a very small -// amount of input, and end up with a very large amount of output. In -// such a pathological inflating mechanism, there'd be no way to tell -// the system to stop doing the transform. A single 4MB write could -// cause the system to run out of memory. -// -// However, even in such a pathological case, only a single written chunk -// would be consumed, and then the rest would wait (un-transformed) until -// the results of the previous transformed chunk were consumed. - -'use strict'; - -module.exports = Transform; - -var Duplex = require('./_stream_duplex'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -util.inherits(Transform, Duplex); - -function TransformState(stream) { - this.afterTransform = function (er, data) { - return afterTransform(stream, er, data); - }; - - this.needTransform = false; - this.transforming = false; - this.writecb = null; - this.writechunk = null; - this.writeencoding = null; -} - -function afterTransform(stream, er, data) { - var ts = stream._transformState; - ts.transforming = false; - - var cb = ts.writecb; - - if (!cb) return stream.emit('error', new Error('no writecb in Transform class')); - - ts.writechunk = null; - ts.writecb = null; - - if (data !== null && data !== undefined) stream.push(data); - - cb(er); - - var rs = stream._readableState; - rs.reading = false; - if (rs.needReadable || rs.length < rs.highWaterMark) { - stream._read(rs.highWaterMark); - } -} - -function Transform(options) { - if (!(this instanceof Transform)) return new Transform(options); - - Duplex.call(this, options); - - this._transformState = new TransformState(this); - - var stream = this; - - // start out asking for a readable event once data is transformed. - this._readableState.needReadable = true; - - // we have implemented the _read method, and done the other things - // that Readable wants before the first _read call, so unset the - // sync guard flag. - this._readableState.sync = false; - - if (options) { - if (typeof options.transform === 'function') this._transform = options.transform; - - if (typeof options.flush === 'function') this._flush = options.flush; - } - - // When the writable side finishes, then flush out anything remaining. - this.once('prefinish', function () { - if (typeof this._flush === 'function') this._flush(function (er, data) { - done(stream, er, data); - });else done(stream); - }); -} - -Transform.prototype.push = function (chunk, encoding) { - this._transformState.needTransform = false; - return Duplex.prototype.push.call(this, chunk, encoding); -}; - -// This is the part where you do stuff! -// override this function in implementation classes. -// 'chunk' is an input chunk. -// -// Call `push(newChunk)` to pass along transformed output -// to the readable side. You may call 'push' zero or more times. -// -// Call `cb(err)` when you are done with this chunk. If you pass -// an error, then that'll put the hurt on the whole operation. If you -// never call cb(), then you'll never get another chunk. -Transform.prototype._transform = function (chunk, encoding, cb) { - throw new Error('_transform() is not implemented'); -}; - -Transform.prototype._write = function (chunk, encoding, cb) { - var ts = this._transformState; - ts.writecb = cb; - ts.writechunk = chunk; - ts.writeencoding = encoding; - if (!ts.transforming) { - var rs = this._readableState; - if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); - } -}; - -// Doesn't matter what the args are here. -// _transform does all the work. -// That we got here means that the readable side wants more data. -Transform.prototype._read = function (n) { - var ts = this._transformState; - - if (ts.writechunk !== null && ts.writecb && !ts.transforming) { - ts.transforming = true; - this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); - } else { - // mark that we need a transform, so that any data that comes in - // will get processed, now that we've asked for it. - ts.needTransform = true; - } -}; - -function done(stream, er, data) { - if (er) return stream.emit('error', er); - - if (data !== null && data !== undefined) stream.push(data); - - // if there's nothing in the write buffer, then that means - // that nothing more will ever be provided - var ws = stream._writableState; - var ts = stream._transformState; - - if (ws.length) throw new Error('Calling transform done when ws.length != 0'); - - if (ts.transforming) throw new Error('Calling transform done when still transforming'); - - return stream.push(null); -} -},{"./_stream_duplex":19,"core-util-is":9,"inherits":12}],23:[function(require,module,exports){ -(function (process){ -// A bit simpler than readable streams. -// Implement an async ._write(chunk, encoding, cb), and it'll handle all -// the drain event emission and buffering. - -'use strict'; - -module.exports = Writable; - -/**/ -var processNextTick = require('process-nextick-args'); -/**/ - -/**/ -var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick; -/**/ - -/**/ -var Duplex; -/**/ - -Writable.WritableState = WritableState; - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -/**/ -var internalUtil = { - deprecate: require('util-deprecate') -}; -/**/ - -/**/ -var Stream; -(function () { - try { - Stream = require('st' + 'ream'); - } catch (_) {} finally { - if (!Stream) Stream = require('events').EventEmitter; - } -})(); -/**/ - -var Buffer = require('buffer').Buffer; -/**/ -var bufferShim = require('buffer-shims'); -/**/ - -util.inherits(Writable, Stream); - -function nop() {} - -function WriteReq(chunk, encoding, cb) { - this.chunk = chunk; - this.encoding = encoding; - this.callback = cb; - this.next = null; -} - -function WritableState(options, stream) { - Duplex = Duplex || require('./_stream_duplex'); - - options = options || {}; - - // object stream flag to indicate whether or not this stream - // contains buffers or objects. - this.objectMode = !!options.objectMode; - - if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode; - - // the point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write() - var hwm = options.highWaterMark; - var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; - - // cast to ints. - this.highWaterMark = ~ ~this.highWaterMark; - - // drain event flag. - this.needDrain = false; - // at the start of calling end() - this.ending = false; - // when end() has been called, and returned - this.ended = false; - // when 'finish' is emitted - this.finished = false; - - // should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. - var noDecode = options.decodeStrings === false; - this.decodeStrings = !noDecode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. - this.length = 0; - - // a flag to see when we're in the middle of a write. - this.writing = false; - - // when true all writes will be buffered until .uncork() call - this.corked = 0; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // a flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. - this.bufferProcessing = false; - - // the callback that's passed to _write(chunk,cb) - this.onwrite = function (er) { - onwrite(stream, er); - }; - - // the callback that the user supplies to write(chunk,encoding,cb) - this.writecb = null; - - // the amount that is being written when _write is called. - this.writelen = 0; - - this.bufferedRequest = null; - this.lastBufferedRequest = null; - - // number of pending user-supplied write callbacks - // this must be 0 before 'finish' can be emitted - this.pendingcb = 0; - - // emit prefinish if the only thing we're waiting for is _write cbs - // This is relevant for synchronous Transform streams - this.prefinished = false; - - // True if the error was already emitted and should not be thrown again - this.errorEmitted = false; - - // count buffered requests - this.bufferedRequestCount = 0; - - // allocate the first CorkedRequest, there is always - // one allocated and free to use, and we maintain at most two - this.corkedRequestsFree = new CorkedRequest(this); -} - -WritableState.prototype.getBuffer = function getBuffer() { - var current = this.bufferedRequest; - var out = []; - while (current) { - out.push(current); - current = current.next; - } - return out; -}; - -(function () { - try { - Object.defineProperty(WritableState.prototype, 'buffer', { - get: internalUtil.deprecate(function () { - return this.getBuffer(); - }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.') - }); - } catch (_) {} -})(); - -// Test _writableState for inheritance to account for Duplex streams, -// whose prototype chain only points to Readable. -var realHasInstance; -if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { - realHasInstance = Function.prototype[Symbol.hasInstance]; - Object.defineProperty(Writable, Symbol.hasInstance, { - value: function (object) { - if (realHasInstance.call(this, object)) return true; - - return object && object._writableState instanceof WritableState; - } - }); -} else { - realHasInstance = function (object) { - return object instanceof this; - }; -} - -function Writable(options) { - Duplex = Duplex || require('./_stream_duplex'); - - // Writable ctor is applied to Duplexes, too. - // `realHasInstance` is necessary because using plain `instanceof` - // would return false, as no `_writableState` property is attached. - - // Trying to use the custom `instanceof` for Writable here will also break the - // Node.js LazyTransform implementation, which has a non-trivial getter for - // `_writableState` that would lead to infinite recursion. - if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { - return new Writable(options); - } - - this._writableState = new WritableState(options, this); - - // legacy. - this.writable = true; - - if (options) { - if (typeof options.write === 'function') this._write = options.write; - - if (typeof options.writev === 'function') this._writev = options.writev; - } - - Stream.call(this); -} - -// Otherwise people can pipe Writable streams, which is just wrong. -Writable.prototype.pipe = function () { - this.emit('error', new Error('Cannot pipe, not readable')); -}; - -function writeAfterEnd(stream, cb) { - var er = new Error('write after end'); - // TODO: defer error events consistently everywhere, not just the cb - stream.emit('error', er); - processNextTick(cb, er); -} - -// If we get something that is not a buffer, string, null, or undefined, -// and we're not in objectMode, then that's an error. -// Otherwise stream chunks are all considered to be of length=1, and the -// watermarks determine how many objects to keep in the buffer, rather than -// how many bytes or characters. -function validChunk(stream, state, chunk, cb) { - var valid = true; - var er = false; - // Always throw error if a null is written - // if we are not in object mode then throw - // if it is not a buffer, string, or undefined. - if (chunk === null) { - er = new TypeError('May not write null values to stream'); - } else if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { - er = new TypeError('Invalid non-string/buffer chunk'); - } - if (er) { - stream.emit('error', er); - processNextTick(cb, er); - valid = false; - } - return valid; -} - -Writable.prototype.write = function (chunk, encoding, cb) { - var state = this._writableState; - var ret = false; - - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (Buffer.isBuffer(chunk)) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; - - if (typeof cb !== 'function') cb = nop; - - if (state.ended) writeAfterEnd(this, cb);else if (validChunk(this, state, chunk, cb)) { - state.pendingcb++; - ret = writeOrBuffer(this, state, chunk, encoding, cb); - } - - return ret; -}; - -Writable.prototype.cork = function () { - var state = this._writableState; - - state.corked++; -}; - -Writable.prototype.uncork = function () { - var state = this._writableState; - - if (state.corked) { - state.corked--; - - if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); - } -}; - -Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { - // node::ParseEncoding() requires lower case. - if (typeof encoding === 'string') encoding = encoding.toLowerCase(); - if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); - this._writableState.defaultEncoding = encoding; - return this; -}; - -function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { - chunk = bufferShim.from(chunk, encoding); - } - return chunk; -} - -// if we're already writing something, then just put this -// in the queue, and wait our turn. Otherwise, call _write -// If we return false, then we need a drain event, so set that flag. -function writeOrBuffer(stream, state, chunk, encoding, cb) { - chunk = decodeChunk(state, chunk, encoding); - - if (Buffer.isBuffer(chunk)) encoding = 'buffer'; - var len = state.objectMode ? 1 : chunk.length; - - state.length += len; - - var ret = state.length < state.highWaterMark; - // we must ensure that previous needDrain will not be reset to false. - if (!ret) state.needDrain = true; - - if (state.writing || state.corked) { - var last = state.lastBufferedRequest; - state.lastBufferedRequest = new WriteReq(chunk, encoding, cb); - if (last) { - last.next = state.lastBufferedRequest; - } else { - state.bufferedRequest = state.lastBufferedRequest; - } - state.bufferedRequestCount += 1; - } else { - doWrite(stream, state, false, len, chunk, encoding, cb); - } - - return ret; -} - -function doWrite(stream, state, writev, len, chunk, encoding, cb) { - state.writelen = len; - state.writecb = cb; - state.writing = true; - state.sync = true; - if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); - state.sync = false; -} - -function onwriteError(stream, state, sync, er, cb) { - --state.pendingcb; - if (sync) processNextTick(cb, er);else cb(er); - - stream._writableState.errorEmitted = true; - stream.emit('error', er); -} - -function onwriteStateUpdate(state) { - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; -} - -function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; - - onwriteStateUpdate(state); - - if (er) onwriteError(stream, state, sync, er, cb);else { - // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(state); - - if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { - clearBuffer(stream, state); - } - - if (sync) { - /**/ - asyncWrite(afterWrite, stream, state, finished, cb); - /**/ - } else { - afterWrite(stream, state, finished, cb); - } - } -} - -function afterWrite(stream, state, finished, cb) { - if (!finished) onwriteDrain(stream, state); - state.pendingcb--; - cb(); - finishMaybe(stream, state); -} - -// Must force callback to be called on nextTick, so that we don't -// emit 'drain' before the write() consumer gets the 'false' return -// value, and has a chance to attach a 'drain' listener. -function onwriteDrain(stream, state) { - if (state.length === 0 && state.needDrain) { - state.needDrain = false; - stream.emit('drain'); - } -} - -// if there's something in the buffer waiting, then process it -function clearBuffer(stream, state) { - state.bufferProcessing = true; - var entry = state.bufferedRequest; - - if (stream._writev && entry && entry.next) { - // Fast case, write everything using _writev() - var l = state.bufferedRequestCount; - var buffer = new Array(l); - var holder = state.corkedRequestsFree; - holder.entry = entry; - - var count = 0; - while (entry) { - buffer[count] = entry; - entry = entry.next; - count += 1; - } - - doWrite(stream, state, true, state.length, buffer, '', holder.finish); - - // doWrite is almost always async, defer these to save a bit of time - // as the hot path ends with doWrite - state.pendingcb++; - state.lastBufferedRequest = null; - if (holder.next) { - state.corkedRequestsFree = holder.next; - holder.next = null; - } else { - state.corkedRequestsFree = new CorkedRequest(state); - } - } else { - // Slow case, write chunks one-by-one - while (entry) { - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; - - doWrite(stream, state, false, len, chunk, encoding, cb); - entry = entry.next; - // if we didn't call the onwrite immediately, then - // it means that we need to wait until it does. - // also, that means that the chunk and cb are currently - // being processed, so move the buffer counter past them. - if (state.writing) { - break; - } - } - - if (entry === null) state.lastBufferedRequest = null; - } - - state.bufferedRequestCount = 0; - state.bufferedRequest = entry; - state.bufferProcessing = false; -} - -Writable.prototype._write = function (chunk, encoding, cb) { - cb(new Error('_write() is not implemented')); -}; - -Writable.prototype._writev = null; - -Writable.prototype.end = function (chunk, encoding, cb) { - var state = this._writableState; - - if (typeof chunk === 'function') { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); - - // .end() fully uncorks - if (state.corked) { - state.corked = 1; - this.uncork(); - } - - // ignore unnecessary end() calls. - if (!state.ending && !state.finished) endWritable(this, state, cb); -}; - -function needFinish(state) { - return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; -} - -function prefinish(stream, state) { - if (!state.prefinished) { - state.prefinished = true; - stream.emit('prefinish'); - } -} - -function finishMaybe(stream, state) { - var need = needFinish(state); - if (need) { - if (state.pendingcb === 0) { - prefinish(stream, state); - state.finished = true; - stream.emit('finish'); - } else { - prefinish(stream, state); - } - } - return need; -} - -function endWritable(stream, state, cb) { - state.ending = true; - finishMaybe(stream, state); - if (cb) { - if (state.finished) processNextTick(cb);else stream.once('finish', cb); - } - state.ended = true; - stream.writable = false; -} - -// It seems a linked list but it is not -// there will be only 2 of these for each stream -function CorkedRequest(state) { - var _this = this; - - this.next = null; - this.entry = null; - - this.finish = function (err) { - var entry = _this.entry; - _this.entry = null; - while (entry) { - var cb = entry.callback; - state.pendingcb--; - cb(err); - entry = entry.next; - } - if (state.corkedRequestsFree) { - state.corkedRequestsFree.next = _this; - } else { - state.corkedRequestsFree = _this; - } - }; -} -}).call(this,require('_process')) -},{"./_stream_duplex":19,"_process":17,"buffer":35,"buffer-shims":8,"core-util-is":9,"events":10,"inherits":12,"process-nextick-args":16,"util-deprecate":32}],24:[function(require,module,exports){ -'use strict'; - -var Buffer = require('buffer').Buffer; -/**/ -var bufferShim = require('buffer-shims'); -/**/ - -module.exports = BufferList; - -function BufferList() { - this.head = null; - this.tail = null; - this.length = 0; -} - -BufferList.prototype.push = function (v) { - var entry = { data: v, next: null }; - if (this.length > 0) this.tail.next = entry;else this.head = entry; - this.tail = entry; - ++this.length; -}; - -BufferList.prototype.unshift = function (v) { - var entry = { data: v, next: this.head }; - if (this.length === 0) this.tail = entry; - this.head = entry; - ++this.length; -}; - -BufferList.prototype.shift = function () { - if (this.length === 0) return; - var ret = this.head.data; - if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; - --this.length; - return ret; -}; - -BufferList.prototype.clear = function () { - this.head = this.tail = null; - this.length = 0; -}; - -BufferList.prototype.join = function (s) { - if (this.length === 0) return ''; - var p = this.head; - var ret = '' + p.data; - while (p = p.next) { - ret += s + p.data; - }return ret; -}; - -BufferList.prototype.concat = function (n) { - if (this.length === 0) return bufferShim.alloc(0); - if (this.length === 1) return this.head.data; - var ret = bufferShim.allocUnsafe(n >>> 0); - var p = this.head; - var i = 0; - while (p) { - p.data.copy(ret, i); - i += p.data.length; - p = p.next; - } - return ret; -}; -},{"buffer":35,"buffer-shims":8}],25:[function(require,module,exports){ -module.exports = require("./lib/_stream_passthrough.js") - -},{"./lib/_stream_passthrough.js":20}],26:[function(require,module,exports){ -(function (process){ -var Stream = (function (){ - try { - return require('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify - } catch(_){} -}()); -exports = module.exports = require('./lib/_stream_readable.js'); -exports.Stream = Stream || exports; -exports.Readable = exports; -exports.Writable = require('./lib/_stream_writable.js'); -exports.Duplex = require('./lib/_stream_duplex.js'); -exports.Transform = require('./lib/_stream_transform.js'); -exports.PassThrough = require('./lib/_stream_passthrough.js'); - -if (!process.browser && process.env.READABLE_STREAM === 'disable' && Stream) { - module.exports = Stream; -} - -}).call(this,require('_process')) -},{"./lib/_stream_duplex.js":19,"./lib/_stream_passthrough.js":20,"./lib/_stream_readable.js":21,"./lib/_stream_transform.js":22,"./lib/_stream_writable.js":23,"_process":17}],27:[function(require,module,exports){ -module.exports = require("./lib/_stream_transform.js") - -},{"./lib/_stream_transform.js":22}],28:[function(require,module,exports){ -module.exports = require("./lib/_stream_writable.js") - -},{"./lib/_stream_writable.js":23}],29:[function(require,module,exports){ -(function (Buffer){ -;(function (sax) { // wrapper for non-node envs - sax.parser = function (strict, opt) { return new SAXParser(strict, opt) } - sax.SAXParser = SAXParser - sax.SAXStream = SAXStream - sax.createStream = createStream - - // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns. - // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)), - // since that's the earliest that a buffer overrun could occur. This way, checks are - // as rare as required, but as often as necessary to ensure never crossing this bound. - // Furthermore, buffers are only tested at most once per write(), so passing a very - // large string into write() might have undesirable effects, but this is manageable by - // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme - // edge case, result in creating at most one complete copy of the string passed in. - // Set to Infinity to have unlimited buffers. - sax.MAX_BUFFER_LENGTH = 64 * 1024 - - var buffers = [ - 'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype', - 'procInstName', 'procInstBody', 'entity', 'attribName', - 'attribValue', 'cdata', 'script' - ] - - sax.EVENTS = [ - 'text', - 'processinginstruction', - 'sgmldeclaration', - 'doctype', - 'comment', - 'opentagstart', - 'attribute', - 'opentag', - 'closetag', - 'opencdata', - 'cdata', - 'closecdata', - 'error', - 'end', - 'ready', - 'script', - 'opennamespace', - 'closenamespace' - ] - - function SAXParser (strict, opt) { - if (!(this instanceof SAXParser)) { - return new SAXParser(strict, opt) - } - - var parser = this - clearBuffers(parser) - parser.q = parser.c = '' - parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH - parser.opt = opt || {} - parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags - parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase' - parser.tags = [] - parser.closed = parser.closedRoot = parser.sawRoot = false - parser.tag = parser.error = null - parser.strict = !!strict - parser.noscript = !!(strict || parser.opt.noscript) - parser.state = S.BEGIN - parser.strictEntities = parser.opt.strictEntities - parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES) - parser.attribList = [] - - // namespaces form a prototype chain. - // it always points at the current tag, - // which protos to its parent tag. - if (parser.opt.xmlns) { - parser.ns = Object.create(rootNS) - } - - // mostly just for error reporting - parser.trackPosition = parser.opt.position !== false - if (parser.trackPosition) { - parser.position = parser.line = parser.column = 0 - } - emit(parser, 'onready') - } - - if (!Object.create) { - Object.create = function (o) { - function F () {} - F.prototype = o - var newf = new F() - return newf - } - } - - if (!Object.keys) { - Object.keys = function (o) { - var a = [] - for (var i in o) if (o.hasOwnProperty(i)) a.push(i) - return a - } - } - - function checkBufferLength (parser) { - var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10) - var maxActual = 0 - for (var i = 0, l = buffers.length; i < l; i++) { - var len = parser[buffers[i]].length - if (len > maxAllowed) { - // Text/cdata nodes can get big, and since they're buffered, - // we can get here under normal conditions. - // Avoid issues by emitting the text node now, - // so at least it won't get any bigger. - switch (buffers[i]) { - case 'textNode': - closeText(parser) - break - - case 'cdata': - emitNode(parser, 'oncdata', parser.cdata) - parser.cdata = '' - break - - case 'script': - emitNode(parser, 'onscript', parser.script) - parser.script = '' - break - - default: - error(parser, 'Max buffer length exceeded: ' + buffers[i]) - } - } - maxActual = Math.max(maxActual, len) - } - // schedule the next check for the earliest possible buffer overrun. - var m = sax.MAX_BUFFER_LENGTH - maxActual - parser.bufferCheckPosition = m + parser.position - } - - function clearBuffers (parser) { - for (var i = 0, l = buffers.length; i < l; i++) { - parser[buffers[i]] = '' - } - } - - function flushBuffers (parser) { - closeText(parser) - if (parser.cdata !== '') { - emitNode(parser, 'oncdata', parser.cdata) - parser.cdata = '' - } - if (parser.script !== '') { - emitNode(parser, 'onscript', parser.script) - parser.script = '' - } - } - - SAXParser.prototype = { - end: function () { end(this) }, - write: write, - resume: function () { this.error = null; return this }, - close: function () { return this.write(null) }, - flush: function () { flushBuffers(this) } - } - - var Stream - try { - Stream = require('stream').Stream - } catch (ex) { - Stream = function () {} - } - - var streamWraps = sax.EVENTS.filter(function (ev) { - return ev !== 'error' && ev !== 'end' - }) - - function createStream (strict, opt) { - return new SAXStream(strict, opt) - } - - function SAXStream (strict, opt) { - if (!(this instanceof SAXStream)) { - return new SAXStream(strict, opt) - } - - Stream.apply(this) - - this._parser = new SAXParser(strict, opt) - this.writable = true - this.readable = true - - var me = this - - this._parser.onend = function () { - me.emit('end') - } - - this._parser.onerror = function (er) { - me.emit('error', er) - - // if didn't throw, then means error was handled. - // go ahead and clear error, so we can write again. - me._parser.error = null - } - - this._decoder = null - - streamWraps.forEach(function (ev) { - Object.defineProperty(me, 'on' + ev, { - get: function () { - return me._parser['on' + ev] - }, - set: function (h) { - if (!h) { - me.removeAllListeners(ev) - me._parser['on' + ev] = h - return h - } - me.on(ev, h) - }, - enumerable: true, - configurable: false - }) - }) - } - - SAXStream.prototype = Object.create(Stream.prototype, { - constructor: { - value: SAXStream - } - }) - - SAXStream.prototype.write = function (data) { - if (typeof Buffer === 'function' && - typeof Buffer.isBuffer === 'function' && - Buffer.isBuffer(data)) { - if (!this._decoder) { - var SD = require('string_decoder').StringDecoder - this._decoder = new SD('utf8') - } - data = this._decoder.write(data) - } - - this._parser.write(data.toString()) - this.emit('data', data) - return true - } - - SAXStream.prototype.end = function (chunk) { - if (chunk && chunk.length) { - this.write(chunk) - } - this._parser.end() - return true - } - - SAXStream.prototype.on = function (ev, handler) { - var me = this - if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) { - me._parser['on' + ev] = function () { - var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments) - args.splice(0, 0, ev) - me.emit.apply(me, args) - } - } - - return Stream.prototype.on.call(me, ev, handler) - } - - // character classes and tokens - var whitespace = '\r\n\t ' - - // this really needs to be replaced with character classes. - // XML allows all manner of ridiculous numbers and digits. - - // (Letter | "_" | ":") - var quote = '\'"' - var attribEnd = whitespace + '>' - var CDATA = '[CDATA[' - var DOCTYPE = 'DOCTYPE' - var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace' - var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/' - var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE } - - // turn all the string character sets into character class objects. - whitespace = charClass(whitespace) - - // http://www.w3.org/TR/REC-xml/#NT-NameStartChar - // This implementation works on strings, a single character at a time - // as such, it cannot ever support astral-plane characters (10000-EFFFF) - // without a significant breaking change to either this parser, or the - // JavaScript language. Implementation of an emoji-capable xml parser - // is left as an exercise for the reader. - var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ - - var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/ - - var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ - var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/ - - quote = charClass(quote) - attribEnd = charClass(attribEnd) - - function charClass (str) { - return str.split('').reduce(function (s, c) { - s[c] = true - return s - }, {}) - } - - function isMatch (regex, c) { - return regex.test(c) - } - - function is (charclass, c) { - return charclass[c] - } - - function notMatch (regex, c) { - return !isMatch(regex, c) - } - - function not (charclass, c) { - return !is(charclass, c) - } - - var S = 0 - sax.STATE = { - BEGIN: S++, // leading byte order mark or whitespace - BEGIN_WHITESPACE: S++, // leading whitespace - TEXT: S++, // general stuff - TEXT_ENTITY: S++, // & and such. - OPEN_WAKA: S++, // < - SGML_DECL: S++, // - SCRIPT: S++, //