From c9a7002431c0db6224d595eb5555b916036d4575 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 3 Oct 2019 13:33:20 +0200 Subject: [PATCH] feat(sampiler): translate code samples to Python (#827) Add an initial version of a tool that will parse the TypeScript samples and emit equivalent sample code in Python. For now, its use is limited: * only supports Python * doesn't support properly integrating/compiling with a multi-package build yet. * non-compiling examples may emit contextually incorrect Python code. More work to come in this space. --- packages/jsii-diff/package-lock.json | 136 - .../package-lock.json | 35 - .../jsii-dotnet-runtime/package-lock.json | 6 - packages/jsii-java-runtime/package-lock.json | 6 - packages/jsii-kernel/package-lock.json | 29 - packages/jsii-pacmak/lib/targets/python.ts | 49 +- packages/jsii-pacmak/package-lock.json | 69 - packages/jsii-pacmak/package.json | 1 + .../expected.jsii-calc-base/python/README.md | 1 - .../expected.jsii-calc-lib/python/README.md | 1 - .../test/expected.jsii-calc/python/README.md | 8 +- .../python/src/jsii_calc/__init__.py | 5 +- packages/jsii-pacmak/tsconfig.json | 11 +- packages/jsii-reflect/package-lock.json | 191 - packages/jsii-ruby-runtime/package-lock.json | 41 - packages/jsii-runtime/package-lock.json | 94 +- packages/jsii-sampiler/.gitignore | 5 + packages/jsii-sampiler/README.md | 147 + packages/jsii-sampiler/bin/jsii-sampiler | 2 + packages/jsii-sampiler/bin/jsii-sampiler.ts | 86 + .../jsii-sampiler/examples/controlflow.ts | 15 + packages/jsii-sampiler/examples/incomplete.ts | 11 + packages/jsii-sampiler/lib/converter.ts | 375 ++ packages/jsii-sampiler/lib/index.ts | 3 + packages/jsii-sampiler/lib/jsii/jsii-utils.ts | 63 + .../jsii-sampiler/lib/languages/default.ts | 217 + .../jsii-sampiler/lib/languages/python.ts | 540 ++ .../jsii-sampiler/lib/languages/visualize.ts | 186 + .../lib/markdown/markdown-renderer.ts | 132 + .../jsii-sampiler/lib/markdown/markdown.ts | 101 + .../lib/markdown/replace-code-renderer.ts | 43 + .../lib/markdown/structure-renderer.ts | 55 + packages/jsii-sampiler/lib/o-tree.ts | 201 + packages/jsii-sampiler/lib/translate.ts | 118 + .../jsii-sampiler/lib/typescript/ast-utils.ts | 316 ++ .../jsii-sampiler/lib/typescript/imports.ts | 76 + .../lib/typescript/ts-compiler.ts | 85 + packages/jsii-sampiler/lib/util.ts | 26 + packages/jsii-sampiler/package-lock.json | 4958 +++++++++++++++++ packages/jsii-sampiler/package.json | 45 + .../test/markdown/roundtrip.test.ts | 164 + packages/jsii-sampiler/test/otree.test.ts | 50 + .../jsii-sampiler/test/python/calls.test.ts | 197 + .../jsii-sampiler/test/python/classes.test.ts | 166 + .../test/python/comments.test.ts | 84 + .../test/python/expressions.test.ts | 61 + .../jsii-sampiler/test/python/hiding.test.ts | 60 + .../jsii-sampiler/test/python/imports.test.ts | 26 + .../jsii-sampiler/test/python/misc.test.ts | 9 + packages/jsii-sampiler/test/python/python.ts | 42 + .../test/python/statements.test.ts | 113 + packages/jsii-sampiler/tsconfig.json | 28 + packages/jsii-spec/package-lock.json | 4 - packages/jsii/lib/helpers.ts | 2 +- packages/jsii/package-lock.json | 17 - packages/oo-ascii-tree/package-lock.json | 4 - 56 files changed, 8870 insertions(+), 646 deletions(-) create mode 100644 packages/jsii-sampiler/.gitignore create mode 100644 packages/jsii-sampiler/README.md create mode 100755 packages/jsii-sampiler/bin/jsii-sampiler create mode 100644 packages/jsii-sampiler/bin/jsii-sampiler.ts create mode 100644 packages/jsii-sampiler/examples/controlflow.ts create mode 100644 packages/jsii-sampiler/examples/incomplete.ts create mode 100644 packages/jsii-sampiler/lib/converter.ts create mode 100644 packages/jsii-sampiler/lib/index.ts create mode 100644 packages/jsii-sampiler/lib/jsii/jsii-utils.ts create mode 100644 packages/jsii-sampiler/lib/languages/default.ts create mode 100644 packages/jsii-sampiler/lib/languages/python.ts create mode 100644 packages/jsii-sampiler/lib/languages/visualize.ts create mode 100644 packages/jsii-sampiler/lib/markdown/markdown-renderer.ts create mode 100644 packages/jsii-sampiler/lib/markdown/markdown.ts create mode 100644 packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts create mode 100644 packages/jsii-sampiler/lib/markdown/structure-renderer.ts create mode 100644 packages/jsii-sampiler/lib/o-tree.ts create mode 100644 packages/jsii-sampiler/lib/translate.ts create mode 100644 packages/jsii-sampiler/lib/typescript/ast-utils.ts create mode 100644 packages/jsii-sampiler/lib/typescript/imports.ts create mode 100644 packages/jsii-sampiler/lib/typescript/ts-compiler.ts create mode 100644 packages/jsii-sampiler/lib/util.ts create mode 100644 packages/jsii-sampiler/package-lock.json create mode 100644 packages/jsii-sampiler/package.json create mode 100644 packages/jsii-sampiler/test/markdown/roundtrip.test.ts create mode 100644 packages/jsii-sampiler/test/otree.test.ts create mode 100644 packages/jsii-sampiler/test/python/calls.test.ts create mode 100644 packages/jsii-sampiler/test/python/classes.test.ts create mode 100644 packages/jsii-sampiler/test/python/comments.test.ts create mode 100644 packages/jsii-sampiler/test/python/expressions.test.ts create mode 100644 packages/jsii-sampiler/test/python/hiding.test.ts create mode 100644 packages/jsii-sampiler/test/python/imports.test.ts create mode 100644 packages/jsii-sampiler/test/python/misc.test.ts create mode 100644 packages/jsii-sampiler/test/python/python.ts create mode 100644 packages/jsii-sampiler/test/python/statements.test.ts create mode 100644 packages/jsii-sampiler/tsconfig.json diff --git a/packages/jsii-diff/package-lock.json b/packages/jsii-diff/package-lock.json index b7ec1c3111..8a3cd06c96 100644 --- a/packages/jsii-diff/package-lock.json +++ b/packages/jsii-diff/package-lock.json @@ -1138,12 +1138,6 @@ "rsvp": "^4.8.4" } }, - "case": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz", - "integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1250,11 +1244,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1397,20 +1386,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz", - "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1473,12 +1448,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", - "dev": true - }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -2973,12 +2942,6 @@ } } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3805,63 +3768,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii/-/jsii-0.17.0.tgz", - "integrity": "sha512-gqmjiydYaKPalk1mnjszTkgQOIb2l8yGT3VNrd5cwf9FArNsqNBcYrkgGjbcR5Vn2X7imilBhISj/S0sBW54nQ==", - "dev": true, - "requires": { - "case": "^1.6.2", - "colors": "^1.3.3", - "deep-equal": "^1.1.0", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "log4js": "^5.1.0", - "semver": "^6.3.0", - "sort-json": "^2.0.0", - "spdx-license-list": "^6.1.0", - "typescript": "~3.6.3", - "yargs": "^14.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "typescript": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz", - "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", - "dev": true - } - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-reflect": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.17.0.tgz", - "integrity": "sha512-xwImRGqSjQwPEun4isrCLerdoxKxk+Vs/lhPvatj9fSLpFw56xHZmkHBtwVl5o2jbBuQQGY3C/o6wBFNrlllgw==", - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "oo-ascii-tree": "^0.17.0", - "yargs": "^14.0.0" - } - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3909,11 +3815,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4322,12 +4223,6 @@ "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", "dev": true }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -4380,11 +4275,6 @@ "mimic-fn": "^1.0.0" } }, - "oo-ascii-tree": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.17.0.tgz", - "integrity": "sha512-HgDeHCPtIkWl10uDp9fFk69lfb+iXjvVGXXYEpci+G+B2sg0uqMInccGsgGK306z1qGFe/Vxt4Mocas+OtQcLg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -4694,15 +4584,6 @@ "safe-regex": "^1.1.0" } }, - "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2" - } - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -5127,17 +5008,6 @@ } } }, - "sort-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-json/-/sort-json-2.0.0.tgz", - "integrity": "sha512-OgXPErPJM/rBK5OhzIJ+etib/BmLQ1JY55Nb/ElhoWUec62pXNF/X6DrecHq3NW5OAGX0KxYD7m0HtgB9dvGeA==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "detect-newline": "^2.1.0", - "minimist": "^1.2.0" - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -5213,12 +5083,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "spdx-license-list": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.1.0.tgz", - "integrity": "sha512-xiaE3KtBiylVmZrlux8tHR28HZgZ921HTXbx2fEZaDloRjbBOro79LeKttcQJ5MSDYFKG7in9v2GTAEhcR9/Qg==", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", diff --git a/packages/jsii-dotnet-runtime-test/package-lock.json b/packages/jsii-dotnet-runtime-test/package-lock.json index dab771bf8a..5feee07b50 100644 --- a/packages/jsii-dotnet-runtime-test/package-lock.json +++ b/packages/jsii-dotnet-runtime-test/package-lock.json @@ -325,41 +325,6 @@ "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", "dev": true }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, "yargs": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz", diff --git a/packages/jsii-dotnet-runtime/package-lock.json b/packages/jsii-dotnet-runtime/package-lock.json index 4152818d74..eafaf1972c 100644 --- a/packages/jsii-dotnet-runtime/package-lock.json +++ b/packages/jsii-dotnet-runtime/package-lock.json @@ -128,12 +128,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz", "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true } } } diff --git a/packages/jsii-java-runtime/package-lock.json b/packages/jsii-java-runtime/package-lock.json index b951afbb58..0a11a3ecee 100644 --- a/packages/jsii-java-runtime/package-lock.json +++ b/packages/jsii-java-runtime/package-lock.json @@ -125,12 +125,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz", "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true } } } diff --git a/packages/jsii-kernel/package-lock.json b/packages/jsii-kernel/package-lock.json index 64c733eda3..bc597fa3f1 100644 --- a/packages/jsii-kernel/package-lock.json +++ b/packages/jsii-kernel/package-lock.json @@ -391,14 +391,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-base": { - "version": "file:../jsii-calc-base", - "dev": true - }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -3606,22 +3598,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3678,11 +3654,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 0b36bded99..64c8d4542b 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -3,6 +3,7 @@ import path = require('path'); import { CodeMaker, toSnakeCase } from 'codemaker'; import * as escapeStringRegexp from 'escape-string-regexp'; import * as reflect from 'jsii-reflect'; +import * as sampiler from 'jsii-sampiler'; import * as spec from 'jsii-spec'; import { Stability } from 'jsii-spec'; import { Generator, GeneratorOptions } from '../generator'; @@ -232,7 +233,7 @@ abstract class BasePythonClassType implements PythonType, ISortableType { const bases = classParams.length > 0 ? `(${classParams.join(', ')})` : ''; code.openBlock(`class ${this.pythonName}${bases}`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); this.emitPreamble(code, resolver); @@ -389,7 +390,7 @@ abstract class BaseMethod implements PythonBase { } code.openBlock(`def ${this.pythonName}(${pythonParams.join(', ')}) -> ${returnType}`); - emitDocString(code, this.docs, { arguments: documentableArgs }); + emitDocString(code, this.docs, { arguments: documentableArgs, documentableItem: `method-${this.pythonName}` }); this.emitBody(code, resolver, renderAbstract, forceEmitBody); code.closeBlock(); } @@ -517,7 +518,7 @@ abstract class BaseProperty implements PythonBase { code.line('@abc.abstractmethod'); } code.openBlock(`def ${this.pythonName}(${this.implicitParameter}) -> ${pythonType}`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); if ((this.shouldEmitBody || forceEmitBody) && (!renderAbstract || !this.abstract)) { code.line(`return jsii.${this.jsiiGetMethod}(${this.implicitParameter}, "${this.jsName}")`); } else { @@ -553,7 +554,7 @@ class Interface extends BasePythonClassType { resolver = this.fqn ? resolver.bind(this.fqn) : resolver; const proxyBases: string[] = this.bases.map(b => `jsii.proxy_for(${resolver.resolve({ type: b })})`); code.openBlock(`class ${this.getProxyClassName()}(${proxyBases.join(', ')})`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); code.line(`__jsii_type__ = "${this.fqn}"`); if (this.members.length > 0) { @@ -676,7 +677,7 @@ class Struct extends BasePythonClassType { name: m.pythonName, docs: m.docs, })); - emitDocString(code, this.docs, { arguments: args }); + emitDocString(code, this.docs, { arguments: args, documentableItem: `class-${this.pythonName}` }); } private emitGetter(member: StructField, code: CodeMaker, resolver: TypeResolver) { @@ -747,13 +748,13 @@ class StructField implements PythonBase { } public emitDocString(code: CodeMaker) { - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); } public emit(code: CodeMaker, resolver: TypeResolver) { const resolvedType = this.typeAnnotation(resolver); code.line(`${this.pythonName}: ${resolvedType}`); - emitDocString(code, this.docs); + this.emitDocString(code); } } @@ -932,7 +933,7 @@ class EnumMember implements PythonBase { public emit(code: CodeMaker, _resolver: TypeResolver) { code.line(`${this.pythonName} = "${this.value}"`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `enum-${this.pythonName}` }); } } @@ -1124,7 +1125,9 @@ class Package { } code.openFile('README.md'); - code.line(this.metadata.readme && this.metadata.readme.markdown); + if (this.metadata.readme) { + code.line(convertSnippetsInMarkdown(this.metadata.readme.markdown, 'README.md')); + } code.closeFile('README.md'); // Strip " (build abcdef)" from the jsii version @@ -1764,6 +1767,7 @@ interface DocumentableArgument { function emitDocString(code: CodeMaker, docs: spec.Docs | undefined, options: { arguments?: DocumentableArgument[]; + documentableItem?: string; } = {}) { if ((!docs || Object.keys(docs).length === 0) && !options.arguments) { return; } if (!docs) { docs = {}; } @@ -1799,7 +1803,7 @@ function emitDocString(code: CodeMaker, docs: spec.Docs | undefined, options: { if (docs.remarks) { brk(); - lines.push(...md2rst(docs.remarks || '').split('\n')); + lines.push(...md2rst(convertSnippetsInMarkdown(docs.remarks || '', options.documentableItem || 'docstring')).split('\n')); brk(); } @@ -1827,7 +1831,9 @@ function emitDocString(code: CodeMaker, docs: spec.Docs | undefined, options: { if (docs.example) { brk(); lines.push('Example::'); - for (const line of docs.example.split('\n')) { + const exampleText = convertExample(docs.example, options.documentableItem || 'example'); + + for (const line of exampleText.split('\n')) { lines.push(` ${line}`); } brk(); @@ -1875,3 +1881,24 @@ function isStruct(typeSystem: reflect.TypeSystem, ref: spec.TypeReference): bool const type = typeSystem.tryFindFqn(ref.fqn); return type !== undefined && type.isInterfaceType() && type.isDataType(); } + +const pythonTranslator = new sampiler.PythonVisitor({ + disclaimer: 'Example may have issues. See https://github.com/aws/jsii/issues/826' +}); + +function convertExample(example: string, filename: string): string { + const source = new sampiler.LiteralSource(example, filename); + const result = sampiler.translateTypeScript(source, pythonTranslator); + sampiler.printDiagnostics(result.diagnostics, process.stderr); + return sampiler.renderTree(result.tree); +} + +function convertSnippetsInMarkdown(markdown: string, filename: string): string { + const source = new sampiler.LiteralSource(markdown, filename); + const result = sampiler.translateMarkdown(source, pythonTranslator, { + languageIdentifier: 'python' + }); + // FIXME: This should translate into an exit code somehow + sampiler.printDiagnostics(result.diagnostics, process.stderr); + return sampiler.renderTree(result.tree); +} \ No newline at end of file diff --git a/packages/jsii-pacmak/package-lock.json b/packages/jsii-pacmak/package-lock.json index c73dadc205..12812a0b44 100644 --- a/packages/jsii-pacmak/package-lock.json +++ b/packages/jsii-pacmak/package-lock.json @@ -359,10 +359,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -1111,16 +1107,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "codemaker": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/codemaker/-/codemaker-0.17.0.tgz", - "integrity": "sha512-cjLBnMB6o3P9/U1h+WAR/y3w3uVjKYeVo+TvhJtDBv8fhmGPe5t68cJ++6aXFyUWpOrbX9cAUyfMKVhXqERYPw==", - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "fs-extra": "^8.1.0" - } - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -1144,11 +1130,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3617,46 +3598,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-dotnet-jsonmodel": { - "version": "file:../jsii-dotnet-jsonmodel", - "dev": true - }, - "jsii-dotnet-runtime": { - "version": "file:../jsii-dotnet-runtime", - "dev": true - }, - "jsii-java-runtime": { - "version": "file:../jsii-java-runtime", - "dev": true - }, - "jsii-reflect": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.17.0.tgz", - "integrity": "sha512-xwImRGqSjQwPEun4isrCLerdoxKxk+Vs/lhPvatj9fSLpFw56xHZmkHBtwVl5o2jbBuQQGY3C/o6wBFNrlllgw==", - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "oo-ascii-tree": "^0.17.0", - "yargs": "^14.0.0" - } - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3704,11 +3645,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4184,11 +4120,6 @@ "mimic-fn": "^1.0.0" } }, - "oo-ascii-tree": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.17.0.tgz", - "integrity": "sha512-HgDeHCPtIkWl10uDp9fFk69lfb+iXjvVGXXYEpci+G+B2sg0uqMInccGsgGK306z1qGFe/Vxt4Mocas+OtQcLg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", diff --git a/packages/jsii-pacmak/package.json b/packages/jsii-pacmak/package.json index 44fe5a1b21..66c3f750fc 100644 --- a/packages/jsii-pacmak/package.json +++ b/packages/jsii-pacmak/package.json @@ -40,6 +40,7 @@ "fs-extra": "^8.1.0", "jsii-reflect": "^0.18.0", "jsii-spec": "^0.18.0", + "jsii-sampiler": "^0.18.0", "spdx-license-list": "^6.1.0", "xmlbuilder": "^13.0.2", "yargs": "^14.0.0" diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md b/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md index 8b13789179..e69de29bb2 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md @@ -1 +0,0 @@ - diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md b/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md index 8b13789179..e69de29bb2 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md @@ -1 +0,0 @@ - diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md b/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md index a1643cddc6..e90486664b 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md @@ -12,8 +12,8 @@ heading will be used as the Sphinx topic name. Otherwise, the name of the module ## Code Samples -```ts -/* This is totes a magic comment in here, just you wait! */ -const foo = 'bar'; +```python +# Example may have issues. See https://github.com/aws/jsii/issues/826 +# This is totes a magic comment in here, just you wait! +foo = "bar" ``` - diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py index f415504245..9ee71643fe 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py @@ -763,8 +763,9 @@ class ClassWithDocs(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.ClassWithDocs" :customAttribute:: hasAValue Example:: - function anExample() { - } + # Example may have issues. See https://github.com/aws/jsii/issues/826 + def an_example(): + pass """ def __init__(self) -> None: jsii.create(ClassWithDocs, self, []) diff --git a/packages/jsii-pacmak/tsconfig.json b/packages/jsii-pacmak/tsconfig.json index 1e2a8b26a6..bc7c96dd3b 100644 --- a/packages/jsii-pacmak/tsconfig.json +++ b/packages/jsii-pacmak/tsconfig.json @@ -55,9 +55,10 @@ "include": [ "**/*.ts" ], - "references": [{ - "path": "../jsii-spec" - }, { - "path": "../codemaker" - }] + "references": [ + { "path": "../jsii-spec" }, + { "path": "../codemaker" }, + { "path": "../jsii-sampiler" }, + { "path": "../jsii-reflect" } + ] } diff --git a/packages/jsii-reflect/package-lock.json b/packages/jsii-reflect/package-lock.json index 25c9e29cd5..11fcb1f183 100644 --- a/packages/jsii-reflect/package-lock.json +++ b/packages/jsii-reflect/package-lock.json @@ -385,10 +385,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.2.tgz", @@ -1014,12 +1010,6 @@ "rsvp": "^4.8.4" } }, - "case": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz", - "integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1241,12 +1231,6 @@ } } }, - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1267,20 +1251,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz", - "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1343,12 +1313,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", - "dev": true - }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -2821,12 +2785,6 @@ } } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3658,49 +3616,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii/-/jsii-0.17.0.tgz", - "integrity": "sha512-gqmjiydYaKPalk1mnjszTkgQOIb2l8yGT3VNrd5cwf9FArNsqNBcYrkgGjbcR5Vn2X7imilBhISj/S0sBW54nQ==", - "dev": true, - "requires": { - "case": "^1.6.2", - "colors": "^1.3.3", - "deep-equal": "^1.1.0", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "log4js": "^5.1.0", - "semver": "^6.3.0", - "sort-json": "^2.0.0", - "spdx-license-list": "^6.1.0", - "typescript": "~3.6.3", - "yargs": "^14.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3748,11 +3663,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -3838,36 +3748,6 @@ "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", "dev": true }, - "log4js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-5.1.0.tgz", - "integrity": "sha512-QtXrBGZiIwfwBrH9zF2uQarvBuJ5+Icqx9fW+nQL4pnmPITJw8n6kh3bck5IkcTDBQatDeKqUMXXX41fp0TIqw==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4182,12 +4062,6 @@ } } }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -4240,11 +4114,6 @@ "mimic-fn": "^1.0.0" } }, - "oo-ascii-tree": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.17.0.tgz", - "integrity": "sha512-HgDeHCPtIkWl10uDp9fFk69lfb+iXjvVGXXYEpci+G+B2sg0uqMInccGsgGK306z1qGFe/Vxt4Mocas+OtQcLg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -4546,15 +4415,6 @@ "safe-regex": "^1.1.0" } }, - "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2" - } - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -4701,12 +4561,6 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "rfdc": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", - "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", - "dev": true - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -4981,17 +4835,6 @@ } } }, - "sort-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-json/-/sort-json-2.0.0.tgz", - "integrity": "sha512-OgXPErPJM/rBK5OhzIJ+etib/BmLQ1JY55Nb/ElhoWUec62pXNF/X6DrecHq3NW5OAGX0KxYD7m0HtgB9dvGeA==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "detect-newline": "^2.1.0", - "minimist": "^1.2.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5059,12 +4902,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "spdx-license-list": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.1.0.tgz", - "integrity": "sha512-xiaE3KtBiylVmZrlux8tHR28HZgZ921HTXbx2fEZaDloRjbBOro79LeKttcQJ5MSDYFKG7in9v2GTAEhcR9/Qg==", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -5130,34 +4967,6 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, - "streamroller": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.1.0.tgz", - "integrity": "sha512-Ps7CuQL0RRG0YAigxNehrGfHrLu+jKSSnhiZBwF8uWi62WmtHDQV1OG5gVgV5SAzitcz1GrM3QVgnRO0mXV2hg==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", diff --git a/packages/jsii-ruby-runtime/package-lock.json b/packages/jsii-ruby-runtime/package-lock.json index 3e13defce5..0adf44e8a9 100644 --- a/packages/jsii-ruby-runtime/package-lock.json +++ b/packages/jsii-ruby-runtime/package-lock.json @@ -424,47 +424,6 @@ "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", "dev": true }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - }, "yargs": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz", diff --git a/packages/jsii-runtime/package-lock.json b/packages/jsii-runtime/package-lock.json index 5697a0b555..41db634dbc 100644 --- a/packages/jsii-runtime/package-lock.json +++ b/packages/jsii-runtime/package-lock.json @@ -386,14 +386,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-base": { - "version": "file:../jsii-calc-base", - "dev": true - }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -1475,7 +1467,8 @@ "chownr": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==" + "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", + "dev": true }, "chrome-trace-event": { "version": "1.0.2", @@ -2677,14 +2670,6 @@ "readable-stream": "^2.0.0" } }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "requires": { - "minipass": "^2.6.0" - } - }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -4552,32 +4537,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-kernel": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-kernel/-/jsii-kernel-0.17.0.tgz", - "integrity": "sha512-NEm+th1s/p/n5v867G/btH+k5E6XcYFde5wWdvP4cOsMB7kO4//MGwebJ7KjCDw2RtnZ8k1YiCsWTVoRaDhUrg==", - "requires": { - "jsii-spec": "^0.17.0", - "source-map": "^0.7.3", - "tar": "^4.4.11" - } - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -4617,11 +4576,6 @@ "minimist": "^1.2.0" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4932,23 +4886,6 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "minipass": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.8.6.tgz", - "integrity": "sha512-lFG7d6g3+/UaFDCOtqPiKAC9zngWWsQZl1g5q6gaONqrjq61SX2xFqXMleQiFVyDpYwa018E9hmlAFY22PCb+A==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.2.tgz", - "integrity": "sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ==", - "requires": { - "minipass": "^2.2.1" - } - }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -4992,6 +4929,7 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, "requires": { "minimist": "0.0.8" }, @@ -4999,7 +4937,8 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true } } }, @@ -6025,7 +5964,8 @@ "safe-buffer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true }, "safe-regex": { "version": "1.1.0", @@ -6320,7 +6260,8 @@ "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true }, "source-map-loader": { "version": "0.2.4", @@ -6649,20 +6590,6 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "tar": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.12.tgz", - "integrity": "sha512-4GwpJwdSjIHlUrWd/1yJrl63UqcqjJyVglgIwn4gcG+Lrp9TXpZ1ZRrGLIRBNqLTUvz6yoPJrX4B/MISxY/Ukg==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, "terser": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.2.tgz", @@ -7407,7 +7334,8 @@ "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true }, "yargs": { "version": "13.2.4", diff --git a/packages/jsii-sampiler/.gitignore b/packages/jsii-sampiler/.gitignore new file mode 100644 index 0000000000..176084432b --- /dev/null +++ b/packages/jsii-sampiler/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +*.js +*.tsbuildinfo +node_modules +*.d.ts diff --git a/packages/jsii-sampiler/README.md b/packages/jsii-sampiler/README.md new file mode 100644 index 0000000000..c0ddf4580a --- /dev/null +++ b/packages/jsii-sampiler/README.md @@ -0,0 +1,147 @@ +# jsii-sampiler: a transpiler for code samples + +Utility to transcribe example code snippets from TypeScript to other +jsii languages. + +Has knowledge about jsii language translation conventions to do the +translations. Only supports a limited set of TypeScript language features. + +## Compilability + +The sampiler can translate both code that completely compiles and typechecks, +as well as code that doesn't. + +In case of non-compiling samples the translations will be based off of +grammatical parsing only. This has the downside that we do not have the type +information available to the exact right thing in all instances. + +If the samples don't compile or don't have full type information: + +- No way to declare typed variables for Java and C#. +- Can only "see" the fields of structs as far as they are declared in the same + snippet. Inherited fields or structs declared not in the same snippet are + invisible. +- When we explode a struct parameter into keyword parameters and we pass it on + to another callable, we can't know which keyword arguments the called function + actually takes so we just pass all of them (might be too many). +- When structs contain nested structs, Python and other languages need to know + the types of these fields to generate the right calls. +- Object literals are used both to represent structs as well as to represent + dictionaries, and without type information it's impossible to determine + which is which. + +## Void masking + +In order to make examples compile, boilerplate code may need to be added +that detracts from the example at hand (such as variable declarations +and imports). + +This package supports hiding parts of the original source after +translation. + +To mark special locations in the source tree, we use the `void` +expression keyword and or the `comma` operator feature to attach this +expression to another expression. Both are little-used JavaScript +features that are reliably parsed by TypeScript and do not affect the +semantics of the application in which they appear (so the program +executes the same with or without them). + +A handy mnemonic for this feature is that you can use it to "send your +code into the void". + +### Hiding statements + +Statement hiding looks like this: + +```ts +before(); // will be shown + +void 0; // start hiding (the argument to 'void' doesn't matter) +middle(); // will not be shown +void 'show'; // stop hiding + +after(); // will be shown again +``` + +Void masking only works to the end of the enclosing scope, so in some +cases you can omit the `void 'show'` directive to turn hiding back off. + +To explicit show that code was hidden, pass `'block'` to the void +statement: + + +```ts +before(); +void 'block'; // start hiding, will render a '# ...' +middle(); +``` + +### Hiding expressions + +For hiding expressions, we use `comma` expressions to attach a `void` +statement to an expression value without changing the meaning of the +code. + +Example: + +```ts +foo(1, 2, (void 1, 3)); +``` + +Will render as + +``` +foo(1, 2) +``` + +Also supports a visible ellipsis: + +```ts +const x = (void '...', 3); +``` + +Renders to: + +``` +x = ... +``` + +## Build integration + +This tool has the ability to hide irrelevant parts of the generated code +snippet (see the section called "void masking" below). Because the samples +should be compilable to extract all necessary type information, and because +they could depend on any package, the following steps need to happen: + +* All packages need to be built (by `jsii`). Ideally, the reduced example ends + up in the assembly. +* After all packages have been built, sample snippets should be checked + for compilability and supported language constructs (not all language + features can be translated to other languages). This requires the full + snippets (before reducing). +* After the full samples have been type-checked, their reduced version + can be translated and inserted into the various generated packages by + `jsii-pacmak`. + +To avoid an additional dependency of `jsii` on the `jsii-samples` mechanism, +what we'll do instead is mutating the assembly in-place. So simplified, +the workflow looks like this: + +* All packages get compiled by `jsii`. +* We postprocess all assemblies using `jsii-samples`, extracting code to + a side-archive (`.jsii.samples`) and replacing the original version in the + assembly, and generating all other language versions. This becomes a + translation table, with the key being a hash of the reduced snippet. +* `jsii-pacmak` replaces snippets from the translation table. + +In this process, `jsii-samples` is as much self-contained as possible. It +works on an assembly to produce a lookup file, which `jsii-pacmak` reads. +`jsii-pacmak` has a simple fallback, which is use the unsubtituted example in +case the right example is not available. + +Alternatively, since `jsii` doesn't really provide any facilities to mutate +an assembly in-place, we leave the unreduced examples in the source assembly, +and force all downstream renderers (such as the doc renderer and API tooling) +to use `jsii-samples` to reduce the snippets before presenting them. This is +not ideal but probably the way we're going to go because `jsii` doesn't provide +any tooling to mutate an assembly in-place. diff --git a/packages/jsii-sampiler/bin/jsii-sampiler b/packages/jsii-sampiler/bin/jsii-sampiler new file mode 100755 index 0000000000..d778d67448 --- /dev/null +++ b/packages/jsii-sampiler/bin/jsii-sampiler @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./jsii-sampiler.js'); diff --git a/packages/jsii-sampiler/bin/jsii-sampiler.ts b/packages/jsii-sampiler/bin/jsii-sampiler.ts new file mode 100644 index 0000000000..7e57c7221d --- /dev/null +++ b/packages/jsii-sampiler/bin/jsii-sampiler.ts @@ -0,0 +1,86 @@ +import yargs = require('yargs'); +import { FileSource, isErrorDiagnostic, LiteralSource, printDiagnostics, + renderTree, translateMarkdown, TranslateResult, translateTypeScript } from '../lib'; +import { PythonVisitor } from '../lib/languages/python'; +import { VisualizeAstVisitor } from '../lib/languages/visualize'; + +async function main() { + const argv = yargs + .usage('$0 [args]') + .command('snippet [file]', 'Translate a single snippet', command => command + .positional('file', { type: 'string', describe: 'The file to translate (leave out for stdin)' }) + .option('python', { alias: 'p', boolean: true, description: 'Translate snippets to Python' }) + , async args => { + const result = translateTypeScript( + await makeFileSource(args.file || '-', 'stdin.ts'), + makeVisitor(args)); + renderResult(result); + }) + .command('markdown ', 'Translate a MarkDown file', command => command + .positional('file', { type: 'string', describe: 'The file to translate (leave out for stdin)' }) + .option('python', { alias: 'p', boolean: true, description: 'Translate snippets to Python' }) + , async args => { + const result = translateMarkdown( + await makeFileSource(args.file || '-', 'stdin.md'), + makeVisitor(args)); + renderResult(result); + return 5; + }) + .demandCommand() + .help() + .strict() // Error on wrong command + .version(require('../package.json').version) + .showHelpOnFail(false) + .argv; + + // Evaluating .argv triggers the parsing but the command gets implicitly executed, + // so we don't need the output. + Array.isArray(argv); +} + +function makeVisitor(args: { python?: boolean }) { + if (args.python) { return new PythonVisitor(); } + // Default to visualizing AST, including nodes we don't recognize yet + return new VisualizeAstVisitor(); +} + +async function makeFileSource(fileName: string, stdinName: string) { + if (fileName === '-') { + return new LiteralSource(await readStdin(), stdinName); + } + return new FileSource(fileName); +} + +async function readStdin(): Promise { + process.stdin.setEncoding('utf8'); + + const parts: string[] = []; + + return new Promise((resolve, reject) => { + process.stdin.on('readable', () => { + const chunk = process.stdin.read(); + if (chunk !== null) { parts.push(`${chunk}`); } + }); + + process.stdin.on('error', reject); + process.stdin.on('end', () => resolve(parts.join(''))); + }); +} + +function renderResult(result: TranslateResult) { + process.stdout.write(renderTree(result.tree) + '\n'); + + if (result.diagnostics.length > 0) { + printDiagnostics(result.diagnostics, process.stderr); + + if (result.diagnostics.some(isErrorDiagnostic)) { + process.exit(1); + } + } +} + +main().catch(e => { + // tslint:disable-next-line:no-console + console.error(e); + process.exit(1); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/examples/controlflow.ts b/packages/jsii-sampiler/examples/controlflow.ts new file mode 100644 index 0000000000..4846ae5d1f --- /dev/null +++ b/packages/jsii-sampiler/examples/controlflow.ts @@ -0,0 +1,15 @@ +import lib = require('@aws-cdk/lib'); + +/** + * This squares a value + */ +function squareNumber(x: number, y?: number) { + return x * x; +} + +// This is where the magic happens +if (Math.random() % 2 == 0) { + console.log(squareNumber(3)); +} else { + console.log(squareNumber(6)); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/examples/incomplete.ts b/packages/jsii-sampiler/examples/incomplete.ts new file mode 100644 index 0000000000..12e1a87681 --- /dev/null +++ b/packages/jsii-sampiler/examples/incomplete.ts @@ -0,0 +1,11 @@ +someObject.callSomeFunction(x, { + y: 3 +}); + +/* This is a thing */ +SomeClass.callSomeFunction(x, { + y: 3 +}); + +// Some comment +const obj = new SecondFunction(this, { hello: 1 }); diff --git a/packages/jsii-sampiler/lib/converter.ts b/packages/jsii-sampiler/lib/converter.ts new file mode 100644 index 0000000000..42c540b6b8 --- /dev/null +++ b/packages/jsii-sampiler/lib/converter.ts @@ -0,0 +1,375 @@ +import ts = require('typescript'); +import { NO_SYNTAX, OTree, UnknownSyntax } from './o-tree'; +import { commentRangeFromTextRange, extractMaskingVoidExpression, extractShowingVoidExpression, nodeChildren, + repeatNewlines, scanText } from './typescript/ast-utils'; +import { analyzeImportDeclaration, analyzeImportEquals, ImportStatement } from './typescript/imports'; + +/** + * AST conversion operation + * + * Dispatch the actual conversion to a specific handler which will get the + * appropriate method called for particular AST nodes. The handler may use + * context to modify its own operations when traversing the tree hierarchy, + * the type of which should be expressed via the C parameter. + */ +export class AstConverter { + public readonly diagnostics = new Array(); + public readonly currentContext: C; + + constructor( + private readonly sourceFile: ts.SourceFile, + private readonly typeChecker: ts.TypeChecker, + private readonly handler: AstHandler, + private readonly options: ConvertOptions = {}) { + + this.currentContext = handler.defaultContext; + } + + /** + * Merge the new context with the current context and create a new Converter from it + */ + public updateContext(contextUpdate: C): AstConverter { + const newContext = this.handler.mergeContext(this.currentContext, contextUpdate); + + // Use prototypal inheritance to create a version of 'this' in which only + // 'currentContext' is updated. + return Object.assign(Object.create(this), { + currentContext: newContext + }); + } + + /** + * Convert a single node to an OTree + */ + public convert(node: ts.Node | undefined): OTree { + if (node === undefined) { return NO_SYNTAX; } + + // Basic transform of node + const transformed = this.dispatch(node); + if (!transformed.attachComment) { return transformed; } + + return this.attachLeadingTrivia(node, transformed); + } + + /** + * Convert a set of nodes, filtering out hidden nodes + */ + public convertAll(nodes: ReadonlyArray): OTree[] { + return filterVisible(nodes).map(this.convert.bind(this)); + } + + /** + * Convert a set of nodes, but update the context for the last one. + * + * Takes visibility into account. + */ + public convertLastDifferently(nodes: ReadonlyArray, lastContext: C): OTree[] { + const lastConverter = this.updateContext(lastContext); + + const convert = this.convert.bind(this); + const lastConvert = lastConverter.convert.bind(lastConverter); + + const ret: OTree[] = []; + + const vis = assignVisibility(nodes); + for (let i = 0; i < vis.length; i++) { + const whichConvert = i === vis.length - 1 ? lastConvert : convert; + + const node = vis[i].visible ? vis[i].node : vis[i].maskingVoid; + if (node) { + ret.push(whichConvert(node)); + } + } + + return ret; + } + + public textOf(node: ts.Node): string { + return node.getText(this.sourceFile); + } + + public textAt(pos: number, end: number): string { + return this.sourceFile.text.substring(pos, end); + } + + public typeOfExpression(node: ts.Expression) { + return this.typeChecker.getContextualType(node); + } + + public typeOfType(node: ts.TypeNode): ts.Type { + return this.typeChecker.getTypeFromTypeNode(node); + } + + public report(node: ts.Node, messageText: string, category: ts.DiagnosticCategory = ts.DiagnosticCategory.Error) { + this.diagnostics.push({ + category, code: 0, + messageText, + file: this.sourceFile, + start: node.getStart(this.sourceFile), + length: node.getWidth(this.sourceFile) + }); + } + + public reportUnsupported(node: ts.Node): void { + const nodeKind = ts.SyntaxKind[node.kind]; + // tslint:disable-next-line:max-line-length + this.report(node, `This TypeScript language feature (${nodeKind}) is not supported in examples because we cannot translate it. Please rewrite this example.`); + } + + /** + * Return a newline if the given node is preceded by at least one newline + * + * Used to mirror newline use between matchin brackets (such as { ... } and [ ... ]). + */ + public mirrorNewlineBefore(viz?: ts.Node, suffix: string = ''): string { + if (viz === undefined) { return suffix; } + + // Return a newline if the given node is preceded by newlines + const leadingRanges = scanText(this.sourceFile.text, viz.getFullStart(), viz.getStart(this.sourceFile)); + const newlines = []; + + for (const range of leadingRanges) { + if (range.type === 'other') { + newlines.push(repeatNewlines(this.sourceFile.text.substring(range.pos, range.end))); + } + } + + return (newlines.join('').length > 0 ? '\n' : '') + suffix; + } + + /** + * Dispatch node to handler + */ + private dispatch(tree: ts.Node): OTree { + // Special nodes + if (ts.isEmptyStatement(tree)) { + // Additional semicolon where it doesn't belong. + return NO_SYNTAX; + } + + const visitor = this.handler; + const context = this; + + // Nodes with meaning + if (ts.isSourceFile(tree)) { return visitor.sourceFile(tree, this); } + if (ts.isImportEqualsDeclaration(tree)) { return visitor.importStatement(analyzeImportEquals(tree, context), context); } + if (ts.isImportDeclaration(tree)) { return visitor.importStatement(analyzeImportDeclaration(tree, context), context); } + if (ts.isStringLiteral(tree)) { return visitor.stringLiteral(tree, context); } + if (ts.isFunctionDeclaration(tree)) { return visitor.functionDeclaration(tree, context); } + if (ts.isIdentifier(tree)) { return visitor.identifier(tree, context); } + if (ts.isBlock(tree)) { return visitor.block(tree, context); } + if (ts.isParameter(tree)) { return visitor.parameterDeclaration(tree, context); } + if (ts.isReturnStatement(tree)) { return visitor.returnStatement(tree, context); } + if (ts.isBinaryExpression(tree)) { return visitor.binaryExpression(tree, context); } + if (ts.isIfStatement(tree)) { return visitor.ifStatement(tree, context); } + if (ts.isPropertyAccessExpression(tree)) { return visitor.propertyAccessExpression(tree, context); } + if (ts.isCallExpression(tree)) { return visitor.callExpression(tree, context); } + if (ts.isExpressionStatement(tree)) { return visitor.expressionStatement(tree, context); } + if (ts.isNoSubstitutionTemplateLiteral(tree)) { return visitor.noSubstitutionTemplateLiteral(tree, context); } + if (ts.isToken(tree)) { return visitor.token(tree, context); } + if (ts.isObjectLiteralExpression(tree)) { return visitor.objectLiteralExpression(tree, context); } + if (ts.isNewExpression(tree)) { return visitor.newExpression(tree, context); } + if (ts.isPropertyAssignment(tree)) { return visitor.propertyAssignment(tree, context); } + if (ts.isVariableStatement(tree)) { return visitor.variableStatement(tree, context); } + if (ts.isVariableDeclarationList(tree)) { return visitor.variableDeclarationList(tree, context); } + if (ts.isVariableDeclaration(tree)) { return visitor.variableDeclaration(tree, context); } + if (ts.isJSDoc(tree)) { return visitor.jsDoc(tree, context); } + if (ts.isArrayLiteralExpression(tree)) { return visitor.arrayLiteralExpression(tree, context); } + if (ts.isShorthandPropertyAssignment(tree)) { return visitor.shorthandPropertyAssignment(tree, context); } + if (ts.isForOfStatement(tree)) { return visitor.forOfStatement(tree, context); } + if (ts.isClassDeclaration(tree)) { return visitor.classDeclaration(tree, context); } + if (ts.isConstructorDeclaration(tree)) { return visitor.constructorDeclaration(tree, context); } + if (ts.isPropertyDeclaration(tree)) { return visitor.propertyDeclaration(tree, context); } + if (ts.isMethodDeclaration(tree)) { return visitor.methodDeclaration(tree, context); } + if (ts.isInterfaceDeclaration(tree)) { return visitor.interfaceDeclaration(tree, context); } + if (ts.isPropertySignature(tree)) { return visitor.propertySignature(tree, context); } + if (ts.isAsExpression(tree)) { return visitor.asExpression(tree, context); } + if (ts.isPrefixUnaryExpression(tree)) { return visitor.prefixUnaryExpression(tree, context); } + if (ts.isSpreadAssignment(tree)) { + if (context.textOf(tree) === '...') { return visitor.ellipsis(tree, context); } + return visitor.spreadAssignment(tree, context); + } + if (ts.isSpreadElement(tree)) { + if (context.textOf(tree) === '...') { return visitor.ellipsis(tree, context); } + return visitor.spreadElement(tree, context); + } + if (ts.isTemplateExpression(tree)) { return visitor.templateExpression(tree, context); } + if (ts.isNonNullExpression(tree)) { return visitor.nonNullExpression(tree, context); } + if (ts.isParenthesizedExpression(tree)) { return visitor.parenthesizedExpression(tree, context); } + if (ts.isVoidExpression(tree)) { return visitor.maskingVoidExpression(tree, context); } + + context.reportUnsupported(tree); + + if (this.options.bestEffort !== false) { + // When doing best-effort conversion and we don't understand the node type, just return the complete text of it as-is + return new OTree([context.textOf(tree)]); + } else { + // Otherwise, show a placeholder indicating we don't recognize the type + const nodeKind = ts.SyntaxKind[tree.kind]; + return new UnknownSyntax([`<${nodeKind} ${context.textOf(tree)}>`], [ + '\n', + ...nodeChildren(tree).map(this.convert.bind(this)) + ], { + indent: 2, + }); + } + } + + /** + * Attach any leading whitespace and comments to the given output tree + * + * Regardless of whether it's declared to be able to accept such or not. + */ + private attachLeadingTrivia(node: ts.Node, transformed: OTree): OTree { + // Add comments and leading whitespace + const leadingRanges = scanText(this.sourceFile.text, node.getFullStart(), node.getStart(this.sourceFile)); + + const precede: OTree[] = []; + for (const range of leadingRanges) { + switch (range.type) { + case 'other': + precede.push(new OTree([repeatNewlines(this.sourceFile.text.substring(range.pos, range.end))], [], { + renderOnce: `ws-${range.pos}` + })); + break; + case 'linecomment': + case 'blockcomment': + precede.push(this.handler.commentRange(commentRangeFromTextRange(range), this)); + break; + } + } + + // FIXME: No trailing comments for now, they're too tricky + + if (precede.length > 0 && !transformed.isEmpty) { + return new OTree([...precede, transformed], [], { canBreakLine: true }); + } else { + return transformed; + } + } +} + +/** + * Interface for AST handlers + * + * C is the type of hierarchical context the handler uses. Context + * needs 2 operations: a constructor for a default context, and a + * merge operation to combine 2 contexts to yield a new one. + * + * Otherwise, the handler should return an OTree for every type + * of AST node. + */ +export interface AstHandler { + readonly defaultContext: C; + mergeContext(old: C, update: C): C; + + sourceFile(node: ts.SourceFile, context: AstConverter): OTree; + commentRange(node: ts.CommentRange, context: AstConverter): OTree; + importStatement(node: ImportStatement, context: AstConverter): OTree; + stringLiteral(node: ts.StringLiteral, children: AstConverter): OTree; + functionDeclaration(node: ts.FunctionDeclaration, children: AstConverter): OTree; + identifier(node: ts.Identifier, children: AstConverter): OTree; + block(node: ts.Block, children: AstConverter): OTree; + parameterDeclaration(node: ts.ParameterDeclaration, children: AstConverter): OTree; + returnStatement(node: ts.ReturnStatement, context: AstConverter): OTree; + binaryExpression(node: ts.BinaryExpression, context: AstConverter): OTree; + ifStatement(node: ts.IfStatement, context: AstConverter): OTree; + propertyAccessExpression(node: ts.PropertyAccessExpression, context: AstConverter): OTree; + callExpression(node: ts.CallExpression, context: AstConverter): OTree; + expressionStatement(node: ts.ExpressionStatement, context: AstConverter): OTree; + token(node: ts.Token, context: AstConverter): OTree; + objectLiteralExpression(node: ts.ObjectLiteralExpression, context: AstConverter): OTree; + newExpression(node: ts.NewExpression, context: AstConverter): OTree; + propertyAssignment(node: ts.PropertyAssignment, context: AstConverter): OTree; + variableStatement(node: ts.VariableStatement, context: AstConverter): OTree; + variableDeclarationList(node: ts.VariableDeclarationList, context: AstConverter): OTree; + variableDeclaration(node: ts.VariableDeclaration, context: AstConverter): OTree; + jsDoc(node: ts.JSDoc, context: AstConverter): OTree; + arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: AstConverter): OTree; + shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: AstConverter): OTree; + forOfStatement(node: ts.ForOfStatement, context: AstConverter): OTree; + classDeclaration(node: ts.ClassDeclaration, context: AstConverter): OTree; + constructorDeclaration(node: ts.ConstructorDeclaration, context: AstConverter): OTree; + propertyDeclaration(node: ts.PropertyDeclaration, context: AstConverter): OTree; + methodDeclaration(node: ts.MethodDeclaration, context: AstConverter): OTree; + interfaceDeclaration(node: ts.InterfaceDeclaration, context: AstConverter): OTree; + propertySignature(node: ts.PropertySignature, context: AstConverter): OTree; + asExpression(node: ts.AsExpression, context: AstConverter): OTree; + prefixUnaryExpression(node: ts.PrefixUnaryExpression, context: AstConverter): OTree; + spreadElement(node: ts.SpreadElement, context: AstConverter): OTree; + spreadAssignment(node: ts.SpreadAssignment, context: AstConverter): OTree; + templateExpression(node: ts.TemplateExpression, context: AstConverter): OTree; + nonNullExpression(node: ts.NonNullExpression, context: AstConverter): OTree; + parenthesizedExpression(node: ts.ParenthesizedExpression, context: AstConverter): OTree; + maskingVoidExpression(node: ts.VoidExpression, context: AstConverter): OTree; + noSubstitutionTemplateLiteral(node: ts.NoSubstitutionTemplateLiteral, context: AstConverter): OTree; + + // Not a node, called when we recognize a spread element/assignment that is only + // '...' and nothing else. + ellipsis(node: ts.SpreadElement | ts.SpreadAssignment, context: AstConverter): OTree; +} + +export function nimpl(node: ts.Node, context: AstConverter, options: { additionalInfo?: string} = {}) { + const children = nodeChildren(node).map(c => context.convert(c)); + + let syntaxKind = ts.SyntaxKind[node.kind]; + if (syntaxKind === 'FirstPunctuation') { + // These have the same identifier but this name is more descriptive + syntaxKind = 'OpenBraceToken'; + } + + const parts = [`(${syntaxKind}`]; + if (options.additionalInfo) { parts.push(`{${options.additionalInfo}}`); } + parts.push(context.textOf(node)); + + return new UnknownSyntax([parts.join(' ')], children.length > 0 ? ['\n', ...children] : [], { + indent: 2, + suffix: ')', + separator: '\n', + canBreakLine: true + }); +} + +export interface ConvertOptions { + /** + * If enabled, don't translate the text of unknown nodes + * + * @default true + */ + bestEffort?: boolean; +} + +interface ClassifiedNode { + node: ts.Node; + visible: boolean; + maskingVoid?: ts.VoidExpression; +} + +function filterVisible(nodes: ReadonlyArray): ts.Node[] { + return assignVisibility(nodes).map(c => c.visible ? c.node : c.maskingVoid).filter(notUndefined); +} + +function assignVisibility(nodes: ReadonlyArray): ClassifiedNode[] { + const ret: ClassifiedNode[] = []; + + let visible = true; + for (const node of nodes) { + const maskingVoid = extractMaskingVoidExpression(node); + if (visible && maskingVoid) { visible = false; } + + ret.push({ node, maskingVoid, visible }); + + if (!visible) { + const showing = extractShowingVoidExpression(node); + if (showing) { + visible = true; + } + } + } + + return ret; +} + +function notUndefined(x: A | undefined): x is A { + return x !== undefined; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/index.ts b/packages/jsii-sampiler/lib/index.ts new file mode 100644 index 0000000000..16b185ccbe --- /dev/null +++ b/packages/jsii-sampiler/lib/index.ts @@ -0,0 +1,3 @@ +export * from './translate'; +export { renderTree } from './o-tree'; +export { PythonVisitor } from './languages/python'; \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/jsii/jsii-utils.ts b/packages/jsii-sampiler/lib/jsii/jsii-utils.ts new file mode 100644 index 0000000000..278e90cace --- /dev/null +++ b/packages/jsii-sampiler/lib/jsii/jsii-utils.ts @@ -0,0 +1,63 @@ +import ts = require('typescript'); +import { AstConverter } from '../converter'; + +export function isStructInterface(name: string) { + return !name.startsWith('I'); +} + +export function isStructType(type: ts.Type) { + return type.isClassOrInterface() + && hasFlag(type.objectFlags, ts.ObjectFlags.Interface) + && isStructInterface(type.symbol.name); +} + +function hasFlag(flags: A, test: A) { + // tslint:disable-next-line:no-bitwise + return (flags & test) !== 0; +} + +export interface StructProperty { + name: string; + type: ts.Type | undefined; + questionMark: boolean; +} + +export function propertiesOfStruct(type: ts.Type, context: AstConverter): StructProperty[] { + return type.isClassOrInterface() ? type.getProperties().map(s => { + let propType; + let questionMark = false; + + const propSymbol = type.getProperty(s.name)!; + const symbolDecl = propSymbol.valueDeclaration; + if (ts.isPropertyDeclaration(symbolDecl) || ts.isPropertySignature(symbolDecl)) { + questionMark = symbolDecl.questionToken !== undefined; + propType = symbolDecl.type && context.typeOfType(symbolDecl.type); + } + + return { + name: s.name, + type: propType, + questionMark, + }; + }) : []; +} + +export function parameterAcceptsUndefined(param: ts.ParameterDeclaration, type?: ts.Type): boolean { + if (param.initializer !== undefined) { return true; } + if (param.questionToken !== undefined) { return true; } + if (type) { return typeContainsUndefined(type); } + return false; +} + +export function structPropertyAcceptsUndefined(prop: StructProperty): boolean { + return prop.questionMark || (!!prop.type && typeContainsUndefined(prop.type)); +} + +/** + * This is a simplified check that should be good enough for most purposes + */ +function typeContainsUndefined(type: ts.Type): boolean { + if (type.getFlags() === ts.TypeFlags.Undefined) { return true; } + if (type.isUnion()) { return type.types.some(typeContainsUndefined); } + return false; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/languages/default.ts b/packages/jsii-sampiler/lib/languages/default.ts new file mode 100644 index 0000000000..0c405ded07 --- /dev/null +++ b/packages/jsii-sampiler/lib/languages/default.ts @@ -0,0 +1,217 @@ +import ts = require('typescript'); +import { AstConverter, AstHandler, nimpl } from "../converter"; +import { OTree } from '../o-tree'; +import { ImportStatement } from '../typescript/imports'; + +/** + * A basic visitor that applies for most curly-braces-based languages + */ +export abstract class DefaultVisitor implements AstHandler { + public abstract readonly defaultContext: C; + + public abstract mergeContext(old: C, update: C): C; + + public commentRange(node: ts.CommentRange, context: AstConverter): OTree { + return new OTree([ + context.textAt(node.pos, node.end), + node.hasTrailingNewLine ? '\n' : '' + ]); + } + + public sourceFile(node: ts.SourceFile, context: AstConverter): OTree { + return new OTree(context.convertAll(node.statements)); + } + + public jsDoc(_node: ts.JSDoc, _context: AstConverter): OTree { + // Already handled by other doc handlers + return new OTree([]); + } + + public importStatement(node: ImportStatement, context: AstConverter): OTree { + return this.notImplemented(node.node, context); + } + + public functionDeclaration(node: ts.FunctionDeclaration, children: AstConverter): OTree { + return this.notImplemented(node, children); + } + + public stringLiteral(node: ts.StringLiteral, _children: AstConverter): OTree { + return new OTree([JSON.stringify(node.text)]); + } + + public noSubstitutionTemplateLiteral(node: ts.NoSubstitutionTemplateLiteral, _context: AstConverter): OTree { + return new OTree([JSON.stringify(node.text)]); + } + + public identifier(node: ts.Identifier, _children: AstConverter): OTree { + return new OTree([node.text]); + } + + public block(node: ts.Block, children: AstConverter): OTree { + return new OTree(['{'], ['\n', ...children.convertAll(node.statements)], { + indent: 4, + suffix: '}', + }); + } + + public parameterDeclaration(node: ts.ParameterDeclaration, children: AstConverter): OTree { + return this.notImplemented(node, children); + } + + public returnStatement(node: ts.ReturnStatement, children: AstConverter): OTree { + return new OTree(['return ', children.convert(node.expression)]); + } + + public binaryExpression(node: ts.BinaryExpression, context: AstConverter): OTree { + return new OTree([ + context.convert(node.left), + ' ', + context.textOf(node.operatorToken), + ' ', + context.convert(node.right) + ]); + } + + public prefixUnaryExpression(node: ts.PrefixUnaryExpression, context: AstConverter): OTree { + + return new OTree([ + UNARY_OPS[node.operator], + context.convert(node.operand) + ]); + } + + public ifStatement(node: ts.IfStatement, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertyAccessExpression(node: ts.PropertyAccessExpression, context: AstConverter): OTree { + return new OTree([context.convert(node.expression), '.', context.convert(node.name)]); + } + + public callExpression(node: ts.CallExpression, context: AstConverter): OTree { + return new OTree([ + context.convert(node.expression), + '(', + new OTree([], context.convertAll(node.arguments), { separator: ', ' }), + ')']); + } + + public expressionStatement(node: ts.ExpressionStatement, context: AstConverter): OTree { + return new OTree([context.convert(node.expression)], [], { canBreakLine: true }); + } + + public token(node: ts.Token, context: AstConverter): OTree { + return new OTree([context.textOf(node)]); + } + + public objectLiteralExpression(node: ts.ObjectLiteralExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public newExpression(node: ts.NewExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertyAssignment(node: ts.PropertyAssignment, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public variableStatement(node: ts.VariableStatement, context: AstConverter): OTree { + return new OTree([context.convert(node.declarationList)], [], { canBreakLine: true }); + } + + public variableDeclarationList(node: ts.VariableDeclarationList, context: AstConverter): OTree { + return new OTree([], context.convertAll(node.declarations)); + } + + public variableDeclaration(node: ts.VariableDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: AstConverter): OTree { + return new OTree(['['], context.convertAll(node.elements), { + separator: ', ', + suffix: ']', + }); + } + + public shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public forOfStatement(node: ts.ForOfStatement, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public classDeclaration(node: ts.ClassDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public constructorDeclaration(node: ts.ConstructorDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertyDeclaration(node: ts.PropertyDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public methodDeclaration(node: ts.MethodDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public interfaceDeclaration(node: ts.InterfaceDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertySignature(node: ts.PropertySignature, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public asExpression(node: ts.AsExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public spreadElement(node: ts.SpreadElement, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public spreadAssignment(node: ts.SpreadAssignment, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public ellipsis(_node: ts.SpreadElement | ts.SpreadAssignment, _context: AstConverter): OTree { + return new OTree(['...']); + } + + public templateExpression(node: ts.TemplateExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public nonNullExpression(node: ts.NonNullExpression, context: AstConverter): OTree { + // We default we drop the non-null assertion + return context.convert(node.expression); + } + + public parenthesizedExpression(node: ts.ParenthesizedExpression, context: AstConverter): OTree { + return new OTree(['(', context.convert(node.expression), ')']); + } + + public maskingVoidExpression(_node: ts.VoidExpression, _context: AstConverter): OTree { + // Don't render anything by default when nodes are masked + return new OTree([]); + } + + private notImplemented(node: ts.Node, context: AstConverter) { + context.reportUnsupported(node); + return nimpl(node, context); + } +} + +const UNARY_OPS: {[op in ts.PrefixUnaryOperator]: string} = { + [ts.SyntaxKind.PlusPlusToken]: '++', + [ts.SyntaxKind.MinusMinusToken]: '--', + [ts.SyntaxKind.PlusToken]: '+', + [ts.SyntaxKind.MinusToken]: '-', + [ts.SyntaxKind.TildeToken]: '~', + [ts.SyntaxKind.ExclamationToken]: '~', +}; diff --git a/packages/jsii-sampiler/lib/languages/python.ts b/packages/jsii-sampiler/lib/languages/python.ts new file mode 100644 index 0000000000..4c871d3291 --- /dev/null +++ b/packages/jsii-sampiler/lib/languages/python.ts @@ -0,0 +1,540 @@ +import ts = require('typescript'); +import { AstConverter, nimpl } from "../converter"; +import { isStructType, parameterAcceptsUndefined, propertiesOfStruct, StructProperty, structPropertyAcceptsUndefined } from '../jsii/jsii-utils'; +import { NO_SYNTAX, OTree, renderTree } from "../o-tree"; +import { matchAst, nodeOfType, stripCommentMarkers, voidExpressionString } from '../typescript/ast-utils'; +import { ImportStatement } from '../typescript/imports'; +import { startsWithUppercase } from "../util"; +import { DefaultVisitor } from './default'; + +interface StructVar { + variableName: string; + type: ts.Type | undefined; +} + +type ReturnFromTree = { value?: A; }; + +interface PythonLanguageContext { + /** + * Whether we're currently rendering a parameter in tail position + * + * If so, and the parameter is of type struct, explode it to keyword args + * and return its information in `returnExplodedParameter`. + */ + readonly tailPositionParameter?: boolean; + + /** + * Used to return details about any exploded parameter + */ + readonly returnExplodedParameter?: ReturnFromTree; + + /** + * Whether we're currently rendering a value/expression in tail position + * + * If so, and the expression seems to be of a struct type, explode it + * to keyword args. + */ + readonly tailPositionArgument?: boolean; + + /** + * Whether object literal members should render themselves as dict + * members or keyword args + */ + readonly renderObjectLiteralAsKeywords?: boolean; + + /** + * In a code block, if any parameter is exploded, information about the parameter here + */ + readonly explodedParameter?: StructVar; + + /** + * Whether we're rendering a method or property inside a class + */ + readonly inClass?: boolean; + + /** + * If we're in a method, what is it's name + * + * (Used to render super() call.); + */ + readonly currentMethodName?: string; +} + +type PythonVisitorContext = AstConverter; + +export interface PythonVisitorOptions { + disclaimer?: string; +} + +export class PythonVisitor extends DefaultVisitor { + public readonly defaultContext = {}; + + constructor(private readonly options: PythonVisitorOptions = {}) { + super(); + } + + public mergeContext(old: PythonLanguageContext, update: PythonLanguageContext) { + return Object.assign({}, old, update); + } + + public commentRange(node: ts.CommentRange, context: PythonVisitorContext): OTree { + const commentText = stripCommentMarkers(context.textAt(node.pos, node.end), node.kind === ts.SyntaxKind.MultiLineCommentTrivia); + const hashLines = commentText.split('\n').map(l => `# ${l}`).join('\n'); + const needsAdditionalTrailer = node.kind !== ts.SyntaxKind.MultiLineCommentTrivia || !node.hasTrailingNewLine; + + return new OTree([hashLines, needsAdditionalTrailer ? '\n' : ''], [], { + // Make sure comment is rendered exactly once in the output tree, no + // matter how many source nodes it is attached to. + renderOnce: `comment-${node.pos}` + }); + } + + public sourceFile(node: ts.SourceFile, context: PythonVisitorContext): OTree { + const rendered = super.sourceFile(node, context); + if (this.options.disclaimer) { + return new OTree(['# ' + this.options.disclaimer + '\n', rendered]); + } + return rendered; + } + + public importStatement(node: ImportStatement, context: PythonVisitorContext): OTree { + const moduleName = this.convertModuleReference(node.packageName); + if (node.imports.import === 'full') { + return new OTree([`import ${moduleName} as ${mangleIdentifier(node.imports.alias)}`], [], { + canBreakLine: true + }); + } + if (node.imports.import === 'selective') { + const imports = node.imports.elements.map(im => + im.alias + ? `${mangleIdentifier(im.sourceName)} as ${mangleIdentifier(im.alias)}` + : mangleIdentifier(im.sourceName)); + + return new OTree([`from ${moduleName} import ${imports.join(', ')}`], [], { + canBreakLine: true + }); + } + + return nimpl(node.node, context); + } + + public token(node: ts.Token, context: PythonVisitorContext): OTree { + const text = context.textOf(node); + const mapped = TOKEN_REWRITES[text]; + if (mapped) { return new OTree([mapped]); } + return super.token(node, context); + } + + public identifier(node: ts.Identifier, context: PythonVisitorContext) { + const originalIdentifier = node.text; + + // tslint:disable-next-line:max-line-length + const explodedParameter = context.currentContext.explodedParameter; + // tslint:disable-next-line:max-line-length + if (context.currentContext.tailPositionArgument && explodedParameter && explodedParameter.type && explodedParameter.variableName === originalIdentifier) { + return new OTree([], + propertiesOfStruct(explodedParameter.type, context).map(prop => new OTree([prop.name, '=', prop.name])), + { separator: ', ' }); + } + + return new OTree([mangleIdentifier(originalIdentifier)]); + } + + public functionDeclaration(node: ts.FunctionDeclaration, context: PythonVisitorContext): OTree { + return this.functionLike(node, context); + } + + public constructorDeclaration(node: ts.ConstructorDeclaration, context: PythonVisitorContext): OTree { + return this.functionLike(node, context, { isConstructor: true }); + } + + public methodDeclaration(node: ts.MethodDeclaration, context: PythonVisitorContext): OTree { + return this.functionLike(node, context); + } + + public expressionStatement(node: ts.ExpressionStatement, context: PythonVisitorContext): OTree { + const text = context.textOf(node); + if (text === 'true') { return new OTree(['True']); } + if (text === 'false') { return new OTree(['False']); } + + return super.expressionStatement(node, context); + } + + // tslint:disable-next-line:max-line-length + public functionLike(node: ts.FunctionLikeDeclarationBase, context: PythonVisitorContext, opts: { isConstructor?: boolean } = {}): OTree { + const methodName = opts.isConstructor ? '__init__' : renderTree(context.convert(node.name)); + + const [paramDecls, explodedParameter] = this.convertFunctionCallParameters(node.parameters, context); + + const ret = new OTree([ + 'def ', + methodName, + '(', + new OTree([], [ + context.currentContext.inClass ? 'self' : undefined, + ...paramDecls, + ], { + separator: ', ', + }), + '): ', + ], [context.updateContext({ explodedParameter, currentMethodName: methodName }).convert(node.body)], { + canBreakLine: true + }); + + return ret; + } + + public block(node: ts.Block, context: PythonVisitorContext): OTree { + if (node.statements.length === 0) { + return new OTree([], ['\npass'], { indent: 4, canBreakLine: true }); + } + + return new OTree([], context.convertAll(node.statements), { + separator: '', + indent: 4, + canBreakLine: true, + }); + } + + public callExpression(node: ts.CallExpression, context: PythonVisitorContext): OTree { + let expressionText: OTree | string = context.convert(node.expression); + + if (matchAst(node.expression, nodeOfType(ts.SyntaxKind.SuperKeyword)) && context.currentContext.currentMethodName) { + expressionText = 'super().' + context.currentContext.currentMethodName; + } + + return new OTree([ + expressionText, + '(', + this.convertFunctionCallArguments(node.arguments, context), + ')'], [], { canBreakLine: true }); + } + + public propertyAccessExpression(node: ts.PropertyAccessExpression, context: PythonVisitorContext) { + const fullText = context.textOf(node); + if (fullText in BUILTIN_FUNCTIONS) { + return new OTree([BUILTIN_FUNCTIONS[fullText]]); + } + + const explodedParameter = context.currentContext.explodedParameter; + + // We might be in a context where we've exploded this struct into arguments, + // in which case we will return just the accessed variable. + if (explodedParameter && context.textOf(node.expression) === explodedParameter.variableName) { + return context.convert(node.name); + } + + return super.propertyAccessExpression(node, context); + } + + public parameterDeclaration(node: ts.ParameterDeclaration, context: PythonVisitorContext): OTree { + const type = node.type && context.typeOfType(node.type); + + if (context.currentContext.tailPositionParameter && type && isStructType(type)) { + // Return the parameter that we exploded so that we can use this information + // while translating the body. + if (context.currentContext.returnExplodedParameter) { + context.currentContext.returnExplodedParameter.value = { + variableName: context.textOf(node.name), + type, + }; + } + + // Explode to fields + return new OTree([], ['*', ...propertiesOfStruct(type, context).map(renderStructProperty)], { separator: ', ' }); + } + + const suffix = parameterAcceptsUndefined(node, type) ? '=None' : ''; + + return new OTree([context.convert(node.name), suffix]); + + function renderStructProperty(prop: StructProperty): string { + const sfx = structPropertyAcceptsUndefined(prop) ? '=None' : ''; + return prop.name + sfx; + } + } + + public ifStatement(node: ts.IfStatement, context: PythonVisitorContext): OTree { + const ifStmt = new OTree( + ['if ', context.convert(node.expression), ': '], + [context.convert(node.thenStatement)], { canBreakLine: true }); + const elseStmt = node.elseStatement ? new OTree([`else: `], [context.convert(node.elseStatement)], { canBreakLine: true }) : undefined; + + return elseStmt ? new OTree([], [ifStmt, elseStmt], { + separator: '\n', + canBreakLine: true + }) : ifStmt; + } + + public objectLiteralExpression(node: ts.ObjectLiteralExpression, context: PythonVisitorContext): OTree { + const type = context.typeOfExpression(node); + + // We render in one of three modes: + // + // - If we're in tail position, we render as keyword arguments if we don't know + // the type, OR we know the type and the type is a struct. + // - Otherwise, if we know the type AND it's a struct we render a class constructor + // (with keyword arguments for the literal members) + // - Otherwise, we render as a dict literal, using dict literal members. + let prefix = '{'; + let suffix = '}'; + let renderObjectLiteralAsKeywords = false; + + const isUnknownType = !type || !type.symbol; + const isKnownStruct = type && isStructType(type); + + if (context.currentContext.tailPositionArgument && (isUnknownType || isKnownStruct)) { + prefix = ''; + suffix = ''; + renderObjectLiteralAsKeywords = true; + } else if (type && isKnownStruct) { + prefix = type.symbol.name + '('; + suffix = ')'; + renderObjectLiteralAsKeywords = true; + } + + return new OTree([prefix], context.updateContext({ renderObjectLiteralAsKeywords }).convertAll(node.properties), { + suffix: context.mirrorNewlineBefore(node.properties[0], suffix), + separator: ', ', + indent: 4, + }); + } + + public arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: PythonVisitorContext): OTree { + return new OTree(['['], context.convertAll(node.elements), { + suffix: context.mirrorNewlineBefore(node.elements[0], ']'), + separator: ', ', + indent: 4, + }); + } + + public propertyAssignment(node: ts.PropertyAssignment, context: PythonVisitorContext): OTree { + let before = '"'; + let mid = '": '; + + if (context.currentContext.renderObjectLiteralAsKeywords) { + before = ''; + mid = '='; + } + + // node.name is either an identifier or a string literal. The string literal + // needs to be converted differently. + let name = context.convert(node.name); + matchAst(node.name, nodeOfType('stringLiteral', ts.SyntaxKind.StringLiteral), captured => { + name = new OTree([mangleIdentifier(captured.stringLiteral.text)]); + }); + + return new OTree([ + before, + name, + mid, + context.updateContext({ tailPositionArgument: false }).convert(node.initializer) + ], [], { canBreakLine: true }); + } + + public shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: PythonVisitorContext): OTree { + let before = '"'; + let mid = '": '; + + if (context.currentContext.renderObjectLiteralAsKeywords) { + before = ''; + mid = '='; + } + + return new OTree([ + before, + context.convert(node.name), + mid, + context.convert(node.name) + ], [], { canBreakLine: true }); + } + + public newExpression(node: ts.NewExpression, context: PythonVisitorContext): OTree { + return new OTree([ + context.convert(node.expression), + '(', + this.convertFunctionCallArguments(node.arguments, context), + ')' + ], [], { canBreakLine: true }); + } + + public variableDeclaration(node: ts.VariableDeclaration, context: PythonVisitorContext): OTree { + return new OTree([ + context.convert(node.name), + ' = ', + context.convert(node.initializer) + ], [], { canBreakLine: true }); + } + + public thisKeyword() { + return new OTree(['self']); + } + + public forOfStatement(node: ts.ForOfStatement, context: PythonVisitorContext): OTree { + // This is what a "for (const x of ...)" looks like in the AST + let variableName = '???'; + + matchAst(node.initializer, + nodeOfType(ts.SyntaxKind.VariableDeclarationList, + nodeOfType('var', ts.SyntaxKind.VariableDeclaration)), + bindings => { + variableName = mangleIdentifier(context.textOf(bindings.var.name)); + }); + + return new OTree([ + 'for ', + variableName, + ' in ', + context.convert(node.expression), + ': ' + ], [context.convert(node.statement)], { canBreakLine: true }); + } + + public classDeclaration(node: ts.ClassDeclaration, context: PythonVisitorContext): OTree { + const heritage = flat(Array.from(node.heritageClauses || []).map(h => Array.from(h.types))).map(t => context.convert(t.expression)); + const hasHeritage = heritage.length > 0; + + const members = context.updateContext({ inClass: true }).convertAll(node.members); + if (members.length === 0) { + members.push(new OTree(['\npass'], [])); + } + + const ret = new OTree([ + 'class ', + node.name ? context.textOf(node.name) : '???', + hasHeritage ? '(' : '', + ...heritage, + hasHeritage ? ')' : '', + ': ', + ], members, { + indent: 4, + canBreakLine: true + }); + + return ret; + } + + public propertyDeclaration(_node: ts.PropertyDeclaration, _context: PythonVisitorContext): OTree { + return new OTree([]); + } + + /** + * We have to do something special here + * + * Best-effort, we remember the fields of struct interfaces and keep track of + * them. Fortunately we can determine from the name whether what to do. + */ + public interfaceDeclaration(_node: ts.InterfaceDeclaration, _context: PythonVisitorContext): OTree { + // Whatever we do, nothing here will have a representation + return NO_SYNTAX; + } + + public propertySignature(_node: ts.PropertySignature, _context: PythonVisitorContext): OTree { + // Does not represent in Python + return NO_SYNTAX; + } + + public asExpression(node: ts.AsExpression, context: PythonVisitorContext): OTree { + return context.convert(node.expression); + } + + public templateExpression(node: ts.TemplateExpression, context: PythonVisitorContext): OTree { + const parts = ['f"']; + if (node.head.rawText) { parts.push(quoteStringLiteral(node.head.rawText)); } + for (const span of node.templateSpans) { + parts.push('{' + context.textOf(span.expression) + '}'); + if (span.literal.rawText) { parts.push(quoteStringLiteral(span.literal.rawText)); } + } + parts.push('"'); + + return new OTree([parts.join('')]); + } + + public maskingVoidExpression(node: ts.VoidExpression, _context: PythonVisitorContext): OTree { + const arg = voidExpressionString(node); + if (arg === 'block') { return new OTree(['# ...'], [], { canBreakLine: true }); } + if (arg === '...') { return new OTree(['...']); } + return NO_SYNTAX; + } + + protected convertModuleReference(ref: string) { + return ref.replace(/^@/, '').replace(/\//g, '.').replace(/-/g, '_'); + } + + /** + * Convert parameters + * + * If the last one has the type of a known struct, explode to keyword-only arguments. + * + * Returns a pair of [decls, excploded-var-name]. + */ + // tslint:disable-next-line:max-line-length + private convertFunctionCallParameters(params: ts.NodeArray | undefined, context: PythonVisitorContext): [Array, StructVar | undefined] { + if (!params || params.length === 0) { return [[], undefined]; } + + const returnExplodedParameter: ReturnFromTree = {}; + + // Convert the last element differently + const converted: Array = params.length > 0 ? [ + ...context.convertAll(params.slice(0, params.length - 1)), + context.updateContext({ + tailPositionParameter: true, + returnExplodedParameter + }).convert(last(params)) + ] : []; + + return [ converted, returnExplodedParameter.value ]; + } + + /** + * Convert arguments. + * + * If the last argument: + * + * - is an object literal, explode it. + * - is itself an exploded argument in our call signature, explode the fields + */ + private convertFunctionCallArguments(args: ts.NodeArray | undefined, context: PythonVisitorContext) { + if (!args) { return NO_SYNTAX; } + + const converted: Array = context.convertLastDifferently(args, { + tailPositionArgument: true, + }); + + return new OTree([], converted, { separator: ', ', indent: 4 }); + } +} + +function mangleIdentifier(originalIdentifier: string) { + if (startsWithUppercase(originalIdentifier)) { + // Probably a class, leave as-is + return originalIdentifier; + } else { + // Turn into snake-case + return originalIdentifier.replace(/[^A-Z][A-Z]/g, m => m[0].substr(0, 1) + '_' + m.substr(1).toLowerCase()); + } +} + +const BUILTIN_FUNCTIONS: {[key: string]: string} = { + 'console.log': 'print', + 'console.error': 'sys.stderr.write', + 'Math.random': 'random.random' +}; + +const TOKEN_REWRITES: {[key: string]: string} = { + this: 'self', + true: 'True', + false: 'False' +}; + +function flat(xs: A[][]): A[] { + return Array.prototype.concat.apply([], xs); +} + +function last(xs: ReadonlyArray): A { + return xs[xs.length - 1]; +} + +function quoteStringLiteral(x: string) { + return x.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/languages/visualize.ts b/packages/jsii-sampiler/lib/languages/visualize.ts new file mode 100644 index 0000000000..837b0f3c74 --- /dev/null +++ b/packages/jsii-sampiler/lib/languages/visualize.ts @@ -0,0 +1,186 @@ +import ts = require('typescript'); +import { AstConverter, AstHandler, nimpl } from "../converter"; +import { OTree } from '../o-tree'; +import { ImportStatement } from '../typescript/imports'; + +export class VisualizeAstVisitor implements AstHandler { + public readonly defaultContext: void = undefined; + + constructor(private readonly includeHandlerNames?: boolean) { + } + + public mergeContext(_old: void, _update: void): void { + return undefined; + } + + public commentRange(node: ts.CommentRange, context: AstConverter): OTree { + return new OTree(['(Comment', context.textAt(node.pos, node.end)], [], { suffix: ')' }); + } + + public jsDoc(_node: ts.JSDoc, _context: AstConverter): OTree { + // Already handled by other doc handlers + return new OTree([]); + } + + public sourceFile(node: ts.SourceFile, context: AstConverter): OTree { + return new OTree(context.convertAll(node.statements)); + } + + public importStatement(node: ImportStatement, context: AstConverter): OTree { + return this.defaultNode('importStatement', node.node, context); + } + + public functionDeclaration(node: ts.FunctionDeclaration, children: AstConverter): OTree { + return this.defaultNode('functionDeclaration', node, children); + } + + public stringLiteral(node: ts.StringLiteral, children: AstConverter): OTree { + return this.defaultNode('stringLiteral', node, children); + } + + public identifier(node: ts.Identifier, children: AstConverter): OTree { + return this.defaultNode('identifier', node, children); + } + + public block(node: ts.Block, children: AstConverter): OTree { + return this.defaultNode('block', node, children); + } + + public parameterDeclaration(node: ts.ParameterDeclaration, children: AstConverter): OTree { + return this.defaultNode('parameterDeclaration', node, children); + } + + public returnStatement(node: ts.ReturnStatement, children: AstConverter): OTree { + return this.defaultNode('returnStatement', node, children); + } + + public binaryExpression(node: ts.BinaryExpression, children: AstConverter): OTree { + return this.defaultNode('binaryExpression', node, children); + } + + public ifStatement(node: ts.IfStatement, context: AstConverter): OTree { + return this.defaultNode('ifStatement', node, context); + } + + public propertyAccessExpression(node: ts.PropertyAccessExpression, context: AstConverter): OTree { + return this.defaultNode('propertyAccessExpression', node, context); + } + + public callExpression(node: ts.CallExpression, context: AstConverter): OTree { + return this.defaultNode('callExpression', node, context); + } + + public expressionStatement(node: ts.ExpressionStatement, context: AstConverter): OTree { + return this.defaultNode('expressionStatement', node, context); + } + + public token(node: ts.Token, context: AstConverter): OTree { + return this.defaultNode('token', node, context); + } + + public objectLiteralExpression(node: ts.ObjectLiteralExpression, context: AstConverter): OTree { + return this.defaultNode('objectLiteralExpression', node, context); + } + + public newExpression(node: ts.NewExpression, context: AstConverter): OTree { + return this.defaultNode('newExpression', node, context); + } + + public propertyAssignment(node: ts.PropertyAssignment, context: AstConverter): OTree { + return this.defaultNode('propertyAssignment', node, context); + } + + public variableStatement(node: ts.VariableStatement, context: AstConverter): OTree { + return this.defaultNode('variableStatement', node, context); + } + + public variableDeclarationList(node: ts.VariableDeclarationList, context: AstConverter): OTree { + return this.defaultNode('variableDeclarationList', node, context); + } + + public variableDeclaration(node: ts.VariableDeclaration, context: AstConverter): OTree { + return this.defaultNode('variableDeclaration', node, context); + } + + public arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: AstConverter): OTree { + return this.defaultNode('arrayLiteralExpression', node, context); + } + + public shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: AstConverter): OTree { + return this.defaultNode('shorthandPropertyAssignment', node, context); + } + + public forOfStatement(node: ts.ForOfStatement, context: AstConverter): OTree { + return this.defaultNode('forOfStatement', node, context); + } + + public classDeclaration(node: ts.ClassDeclaration, context: AstConverter): OTree { + return this.defaultNode('classDeclaration', node, context); + } + + public constructorDeclaration(node: ts.ConstructorDeclaration, context: AstConverter): OTree { + return this.defaultNode('constructorDeclaration', node, context); + } + + public propertyDeclaration(node: ts.PropertyDeclaration, context: AstConverter): OTree { + return this.defaultNode('propertyDeclaration', node, context); + } + + public methodDeclaration(node: ts.MethodDeclaration, context: AstConverter): OTree { + return this.defaultNode('methodDeclaration', node, context); + } + + public interfaceDeclaration(node: ts.InterfaceDeclaration, context: AstConverter): OTree { + return this.defaultNode('interfaceDeclaration', node, context); + } + + public propertySignature(node: ts.PropertySignature, context: AstConverter): OTree { + return this.defaultNode('propertySignature', node, context); + } + + public asExpression(node: ts.AsExpression, context: AstConverter): OTree { + return this.defaultNode('asExpression', node, context); + } + + public prefixUnaryExpression(node: ts.PrefixUnaryExpression, context: AstConverter): OTree { + return this.defaultNode('prefixUnaryExpression', node, context); + } + + public spreadElement(node: ts.SpreadElement, context: AstConverter): OTree { + return this.defaultNode('spreadElement', node, context); + } + + public spreadAssignment(node: ts.SpreadAssignment, context: AstConverter): OTree { + return this.defaultNode('spreadAssignment', node, context); + } + + public ellipsis(node: ts.SpreadAssignment | ts.SpreadElement, context: AstConverter): OTree { + return this.defaultNode('ellipsis', node, context); + } + + public templateExpression(node: ts.TemplateExpression, context: AstConverter): OTree { + return this.defaultNode('templateExpression', node, context); + } + + public nonNullExpression(node: ts.NonNullExpression, context: AstConverter): OTree { + return this.defaultNode('nonNullExpression', node, context); + } + + public parenthesizedExpression(node: ts.ParenthesizedExpression, context: AstConverter): OTree { + return this.defaultNode('parenthesizedExpression', node, context); + } + + public maskingVoidExpression(node: ts.VoidExpression, context: AstConverter): OTree { + return this.defaultNode('maskingVoidExpression', node, context); + } + + public noSubstitutionTemplateLiteral(node: ts.NoSubstitutionTemplateLiteral, context: AstConverter): OTree { + return this.defaultNode('noSubstitutionTemplateLiteral', node, context); + } + + private defaultNode(handlerName: string, node: ts.Node, context: AstConverter): OTree { + return nimpl(node, context, { + additionalInfo: this.includeHandlerNames ? handlerName : '' + }); + } +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/markdown/markdown-renderer.ts b/packages/jsii-sampiler/lib/markdown/markdown-renderer.ts new file mode 100644 index 0000000000..c876a38b86 --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/markdown-renderer.ts @@ -0,0 +1,132 @@ +import cm = require('commonmark'); +import { cmNodeChildren, CommonMarkRenderer, prefixLines, RendererContext } from './markdown'; + +/** + * A renderer that will render a CommonMark tree back to MarkDown + */ +export class MarkdownRenderer implements CommonMarkRenderer { + public block_quote(_node: cm.Node, context: RendererContext) { + return para(prefixLines('> ', collapsePara(context.content()))); + } + + public code(node: cm.Node, _context: RendererContext) { + return '`' + node.literal + '`'; + } + + public code_block(node: cm.Node, _context: RendererContext) { + return para('```' + (node.info || '') + '\n' + node.literal + '```'); + } + + public text(node: cm.Node, _context: RendererContext) { + return node.literal || ''; + } + + public softbreak(_node: cm.Node, _context: RendererContext) { + return '\n'; + } + + public linebreak(_node: cm.Node, _context: RendererContext) { + return '\\\n'; + } + + public emph(_node: cm.Node, context: RendererContext) { + return `*${context.content()}*`; + } + + public strong(_node: cm.Node, context: RendererContext) { + return `**${context.content()}**`; + } + + public html_inline(node: cm.Node, _context: RendererContext) { + return node.literal || ''; + } + + public html_block(_node: cm.Node, context: RendererContext) { + return `${context.content()}`; + } + + public link(node: cm.Node, context: RendererContext) { + return `[${context.content()}](${node.destination || ''})`; + } + + public image(node: cm.Node, context: RendererContext) { + return `![${context.content()}](${node.destination || ''})`; + } + + public document(_node: cm.Node, context: RendererContext) { + // Remove trailing whitespace on every line + return collapsePara(context.content()).replace(/[ \t]+$/gm, ''); + } + + public paragraph(_node: cm.Node, context: RendererContext) { + return para(context.content()); + } + + public list(node: cm.Node, context: RendererContext) { + // A list is not wrapped in a paragraph, but items may contain paragraphs. + // All elements of a list are definitely 'item's. + const items = []; + + let i = 1; + for (const item of cmNodeChildren(node)) { + const firstLinePrefix = determineItemPrefix(node, i); + const hangingPrefix = ' '.repeat(firstLinePrefix.length); + + const rendered = context.recurse(item); + // Prefix the first line with a different text than subsequent lines + const prefixed = firstLinePrefix + prefixLines(hangingPrefix, rendered).substr(hangingPrefix.length); + + items.push(prefixed); + + i += 1; + } + + return para(items.join('\n')); + } + + public item(_node: cm.Node, context: RendererContext) { + return collapsePara(context.content()); + } + + public heading(node: cm.Node, context: RendererContext) { + return para('#'.repeat(node.level) + ' ' + context.content()); + } + + public thematic_break(_node: cm.Node, _context: RendererContext) { + return '---\n'; + } + + public custom_block(_node: cm.Node, context: RendererContext) { + return `${context.content()}`; + } + + public custom_inline(_node: cm.Node, context: RendererContext) { + return `${context.content()}`; + } +} + +/* +function trimEmptyLines(x: string) { + return x.replace(/^\n+/, '').replace(/\n+$/, ''); +} +*/ + +const PARA_BREAK = '\u001d'; + +function para(x: string) { + return `${PARA_BREAK}${x}${PARA_BREAK}`; +} + +/** + * Collapse paragraph markers + */ +function collapsePara(x: string, brk: string = '\n\n') { + return x.replace(/^\u001d+/, '').replace(/\u001d+$/, '').replace(/\u001d+/g, brk); +} + +function determineItemPrefix(listNode: cm.Node, index: number) { + if (listNode.listType === 'bullet') { + return '* '; + } + return `${index}${listNode.listDelimiter} `; +} diff --git a/packages/jsii-sampiler/lib/markdown/markdown.ts b/packages/jsii-sampiler/lib/markdown/markdown.ts new file mode 100644 index 0000000000..256c29a6a0 --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/markdown.ts @@ -0,0 +1,101 @@ +import cm = require('commonmark'); + +export function transformMarkdown(source: string, renderer: CommonMarkRenderer, transform?: CommonMarkVisitor) { + const parser = new cm.Parser(); + const doc = parser.parse(source); + if (transform) { + visitCommonMarkTree(doc, transform); + } + return renderCommonMarkTree(doc, renderer); +} + +export interface RendererContext { + recurse(node: cm.Node): string; + children(): string[]; + content(): string; +} + +export interface CommonMarkRenderer { + block_quote(node: cm.Node, context: RendererContext): string; + code(node: cm.Node, context: RendererContext): string; + code_block(node: cm.Node, context: RendererContext): string; + text(node: cm.Node, context: RendererContext): string; + softbreak(node: cm.Node, context: RendererContext): string; + linebreak(node: cm.Node, context: RendererContext): string; + emph(node: cm.Node, context: RendererContext): string; + strong(node: cm.Node, context: RendererContext): string; + html_inline(node: cm.Node, context: RendererContext): string; + html_block(node: cm.Node, context: RendererContext): string; + link(node: cm.Node, context: RendererContext): string; + image(node: cm.Node, context: RendererContext): string; + document(node: cm.Node, context: RendererContext): string; + paragraph(node: cm.Node, context: RendererContext): string; + list(node: cm.Node, context: RendererContext): string; + item(node: cm.Node, context: RendererContext): string; + heading(node: cm.Node, context: RendererContext): string; + thematic_break(node: cm.Node, context: RendererContext): string; + custom_block(node: cm.Node, context: RendererContext): string; + custom_inline(node: cm.Node, context: RendererContext): string; +} + +export function renderCommonMarkTree(node: cm.Node, renderer: CommonMarkRenderer) { + const context: RendererContext = { + recurse(n: cm.Node): string { + return renderCommonMarkTree(n, renderer); + }, + + content() { + return this.children().join(''); + }, + + children() { + const parts = []; + for (const child of cmNodeChildren(node)) { + parts.push(renderCommonMarkTree(child, renderer)); + } + return parts; + } + }; + + return renderer[node.type].call(renderer, node, context); +} + +export function visitCommonMarkTree(node: cm.Node, visitor: CommonMarkVisitor) { + visitor[node.type].call(visitor, node); + for (const child of cmNodeChildren(node)) { + visitCommonMarkTree(child, visitor); + } +} + +export function prefixLines(prefix: string, x: string) { + return x.split('\n').map(l => prefix + l).join('\n'); +} + +export function* cmNodeChildren(node: cm.Node): IterableIterator { + for (let child = node.firstChild; child !== null; child = child.next) { + yield child; + } +} + +export interface CommonMarkVisitor { + block_quote(node: cm.Node): void; + code(node: cm.Node): void; + code_block(node: cm.Node): void; + text(node: cm.Node): void; + softbreak(node: cm.Node): void; + linebreak(node: cm.Node): void; + emph(node: cm.Node): void; + strong(node: cm.Node): void; + html_inline(node: cm.Node): void; + html_block(node: cm.Node): void; + link(node: cm.Node): void; + image(node: cm.Node): void; + document(node: cm.Node): void; + paragraph(node: cm.Node): void; + list(node: cm.Node): void; + item(node: cm.Node): void; + heading(node: cm.Node): void; + thematic_break(node: cm.Node): void; + custom_block(node: cm.Node): void; + custom_inline(node: cm.Node): void; +} diff --git a/packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts b/packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts new file mode 100644 index 0000000000..4229e4bd7b --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts @@ -0,0 +1,43 @@ +import cm = require('commonmark'); +import { CommonMarkVisitor } from './markdown'; + +export type CodeReplacer = (code: CodeBlock) => CodeBlock; + +export interface CodeBlock { + source: string; + language: string; +} + +/** + * Renderer that replaces code blocks in a MarkDown document + */ +export class ReplaceCodeTransform implements CommonMarkVisitor { + constructor(private readonly replacer: CodeReplacer) { + } + + public code_block(node: cm.Node) { + const ret = this.replacer({ language: node.info || '', source: node.literal || '' }); + node.info = ret.language; + node.literal = ret.source; + } + + public block_quote(): void { /* nothing */ } + public code(): void { /* nothing */ } + public text(): void { /* nothing */ } + public softbreak(): void { /* nothing */ } + public linebreak(): void { /* nothing */ } + public emph(): void { /* nothing */ } + public strong(): void { /* nothing */ } + public html_inline(): void { /* nothing */ } + public html_block(): void { /* nothing */ } + public link(): void { /* nothing */ } + public image(): void { /* nothing */ } + public document(): void { /* nothing */ } + public paragraph(): void { /* nothing */ } + public list(): void { /* nothing */ } + public item(): void { /* nothing */ } + public heading(): void { /* nothing */ } + public thematic_break(): void { /* nothing */ } + public custom_block(): void { /* nothing */ } + public custom_inline(): void { /* nothing */ } +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/markdown/structure-renderer.ts b/packages/jsii-sampiler/lib/markdown/structure-renderer.ts new file mode 100644 index 0000000000..8e82a9237a --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/structure-renderer.ts @@ -0,0 +1,55 @@ +import cm = require('commonmark'); +import { CommonMarkRenderer, prefixLines, RendererContext } from './markdown'; + +/** + * A renderer that will render a CommonMark tree to show its structure + */ +export class StructureRenderer implements CommonMarkRenderer { + public block_quote(node: cm.Node, context: RendererContext) { return this.handle('block_quote', node, context); } + public code(node: cm.Node, context: RendererContext) { return this.handle('code', node, context); } + public code_block(node: cm.Node, context: RendererContext) { return this.handle('code_block', node, context); } + public text(node: cm.Node, context: RendererContext) { return this.handle('text', node, context); } + public softbreak(node: cm.Node, context: RendererContext) { return this.handle('softbreak', node, context); } + public linebreak(node: cm.Node, context: RendererContext) { return this.handle('linebreak', node, context); } + public emph(node: cm.Node, context: RendererContext) { return this.handle('emph', node, context); } + public strong(node: cm.Node, context: RendererContext) { return this.handle('strong', node, context); } + public html_inline(node: cm.Node, context: RendererContext) { return this.handle('html_inline', node, context); } + public html_block(node: cm.Node, context: RendererContext) { return this.handle('html_block', node, context); } + public link(node: cm.Node, context: RendererContext) { return this.handle('link', node, context); } + public image(node: cm.Node, context: RendererContext) { return this.handle('image', node, context); } + public document(node: cm.Node, context: RendererContext) { return this.handle('document', node, context); } + public paragraph(node: cm.Node, context: RendererContext) { return this.handle('paragraph', node, context); } + public list(node: cm.Node, context: RendererContext) { return this.handle('list', node, context); } + public item(node: cm.Node, context: RendererContext) { return this.handle('item', node, context); } + public heading(node: cm.Node, context: RendererContext) { return this.handle('heading', node, context); } + public thematic_break(node: cm.Node, context: RendererContext) { return this.handle('thematic_break', node, context); } + public custom_block(node: cm.Node, context: RendererContext) { return this.handle('custom_block', node, context); } + public custom_inline(node: cm.Node, context: RendererContext) { return this.handle('custom_inline', node, context); } + + private handle(name: string, node: cm.Node, context: RendererContext) { + const contents = context.content(); + + const enterText = [name, inspectNode(node)].filter(x => x).join(' '); + + if (contents) { + return `(${enterText}\n${prefixLines(' ', contents)})\n`; + } else { + return `(${enterText})\n`; + } + } +} + +function inspectNode(n: cm.Node): string { + const INTERESTING_KEYS = [ + 'literal', 'destination', 'title', 'info', 'level', 'listType', 'listTight', 'listStart', 'listDelimiter', + ]; + const ret: any = {}; + // tslint:disable-next-line:forin + for (const key of INTERESTING_KEYS) { + const value = (n as any)[key]; + if (typeof value === 'string' || typeof value === 'number') { + ret[key] = value; + } + } + return JSON.stringify(ret); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/o-tree.ts b/packages/jsii-sampiler/lib/o-tree.ts new file mode 100644 index 0000000000..a81ae58be5 --- /dev/null +++ b/packages/jsii-sampiler/lib/o-tree.ts @@ -0,0 +1,201 @@ + +export interface OTreeOptions { + /** + * Adjust indentation with the given number + * + * Indentation affects children. + * + * @default 0 + */ + indent?: number; + + /** + * Separate children with the given string + * + * @default '' + */ + separator?: string; + + /** + * Suffix the token after outdenting + * + * @default '' + */ + suffix?: string; + + /** + * Whether this part of the generated syntax is okay to insert newlines and comments + * + * @default false + */ + canBreakLine?: boolean; + + /** + * If set, a unique key which will cause only one node with the given key to be rendered. + * + * The outermost key is the one that will be rendered. + * + * Used to make it easier to keep the state necessary to render comments + * only once in the output tree, rather than keep the state in the + * language rendered. + * + * @default No conditional rendering + */ + renderOnce?: string; +} + +/** + * "Output" Tree + * + * Tree-like structure that holds sequences of trees and strings, which + * can be rendered to an output stream. + */ +export class OTree { + public static simplify(xs: Array): Array { + return xs.filter(notUndefined).filter(notEmpty); + } + + public readonly attachComment: boolean; + + private readonly prefix: Array; + private readonly children: Array; + + constructor( + prefix: Array, + children?: Array, + private readonly options: OTreeOptions = {}) { + + this.prefix = OTree.simplify(prefix); + this.children = OTree.simplify(children || []); + this.attachComment = !!options.canBreakLine; + } + + public write(sink: OTreeSink) { + if (!sink.tagOnce(this.options.renderOnce)) { return; } + + for (const x of this.prefix) { + sink.write(x); + } + + const popIndent = sink.requestIndentChange(this.options.indent || 0); + let mark = sink.mark(); + for (const child of this.children || []) { + if (this.options.separator && mark.wroteNonWhitespaceSinceMark) { sink.write(this.options.separator); } + mark = sink.mark(); + + sink.write(child); + } + + popIndent(); + + if (this.options.suffix) { + sink.write(this.options.suffix); + } + } + + public get isEmpty() { + return this.prefix.length + this.children.length === 0; + } + + public toString() { + return ``; + } +} + +export const NO_SYNTAX = new OTree([]); + +export class UnknownSyntax extends OTree { +} + +export interface SinkMark { + readonly wroteNonWhitespaceSinceMark: boolean; +} + +export class OTreeSink { + private readonly indentLevels: number[] = [0]; + private readonly fragments = new Array(); + private singletonsRendered = new Set(); + private pendingIndentChange = 0; + + public tagOnce(key: string | undefined): boolean { + if (key === undefined) { return true; } + if (this.singletonsRendered.has(key)) { return false; } + this.singletonsRendered.add(key); + return true; + } + + public mark(): SinkMark { + const self = this; + const markIndex = this.fragments.length; + + return { + get wroteNonWhitespaceSinceMark(): boolean { + return self.fragments.slice(markIndex).some(s => !!s.match(/[^\s]/)); + } + }; + } + + public write(text: string | OTree) { + if (text instanceof OTree) { + text.write(this); + } else { + if (containsNewline(text)) { + this.applyPendingIndentChange(); + } + this.append(text.replace(/\n/g, '\n' + ' '.repeat(this.currentIndent))); + } + } + + public requestIndentChange(x: number): () => void { + if (x === 0) { return () => undefined; } + + this.pendingIndentChange = x; + const currentIndentState = this.indentLevels.length; + const self = this; + + // Return a pop function which will reset to the current indent state, + // regardless of whether the indent was actually applied or not. + return () => { + self.indentLevels.splice(currentIndentState); + self.pendingIndentChange = 0; + }; + } + + public toString() { + // Strip trailing whitespace from every line + return this.fragments.join('').replace(/[ \t]+$/gm, ''); + } + + private append(x: string) { + this.fragments.push(x); + } + + private applyPendingIndentChange() { + if (this.pendingIndentChange !== 0) { + this.indentLevels.push(this.currentIndent + this.pendingIndentChange); + this.pendingIndentChange = 0; + } + } + + private get currentIndent() { + return this.indentLevels[this.indentLevels.length - 1]; + } +} + +function notUndefined(x: T | undefined): x is T { + return x !== undefined; +} + +function notEmpty(x: OTree | string) { + return x instanceof OTree ? !x.isEmpty : x !== ''; +} + +export function renderTree(tree: OTree): string { + const sink = new OTreeSink(); + tree.write(sink); + return sink.toString(); +} + +function containsNewline(x: string) { + return x.indexOf('\n') !== -1; +} diff --git a/packages/jsii-sampiler/lib/translate.ts b/packages/jsii-sampiler/lib/translate.ts new file mode 100644 index 0000000000..c9bc42a9ce --- /dev/null +++ b/packages/jsii-sampiler/lib/translate.ts @@ -0,0 +1,118 @@ +import fs = require('fs-extra'); +import ts = require('typescript'); +import { AstConverter, AstHandler, ConvertOptions } from './converter'; +import { transformMarkdown } from './markdown/markdown'; +import { MarkdownRenderer } from './markdown/markdown-renderer'; +import { ReplaceCodeTransform } from './markdown/replace-code-renderer'; +import { OTree, renderTree } from './o-tree'; +import { TypeScriptCompiler } from './typescript/ts-compiler'; +import { inTempDir } from './util'; + +export interface Source { + withFile(fn: (fileName: string) => A): A; + withContents(fn: (fileName: string, contents: string) => A): A; +} + +export class FileSource implements Source { + constructor(private readonly fileName: string) { } + + public withFile(fn: (fileName: string) => A): A { + return fn(this.fileName); + } + + public withContents(fn: (fileName: string, contents: string) => A): A { + const contents = fs.readFileSync(this.fileName, 'utf-8'); + return fn(this.fileName, contents); + } +} + +export class LiteralSource implements Source { + constructor(private readonly source: string, private readonly filenameHint = 'index.ts') { } + + public withFile(fn: (fileName: string) => A): A { + return inTempDir(() => { + fs.writeFileSync(this.filenameHint, this.source); + return fn(this.filenameHint); + }); + } + + public withContents(fn: (fileName: string, contents: string) => A): A { + return fn(this.filenameHint, this.source); + } +} + +export interface TranslateMarkdownOptions extends ConvertOptions { + /** + * What language to put in the returned markdown blocks + */ + languageIdentifier?: string; +} + +export function translateMarkdown(markdown: Source, visitor: AstHandler, options: TranslateMarkdownOptions = {}): TranslateResult { + const compiler = new TypeScriptCompiler(); + + let index = 0; + const diagnostics = new Array(); + + const translatedMarkdown = markdown.withContents((filename, contents) => { + return transformMarkdown(contents, new MarkdownRenderer(), new ReplaceCodeTransform(code => { + if (code.language !== 'typescript' && code.language !== 'ts') { return code; } + + index += 1; + const snippetSource = new LiteralSource(code.source, `${filename}-snippet${index}.ts`); + const snippetTranslation = translateSnippet(snippetSource, compiler, visitor, options); + + diagnostics.push(...snippetTranslation.diagnostics); + + return { language: options.languageIdentifier || '', source: renderTree(snippetTranslation.tree) + '\n' }; + })); + }); + + return { tree: new OTree([translatedMarkdown]), diagnostics }; +} + +export type TranslateOptions = ConvertOptions; + +export function translateTypeScript(source: Source, visitor: AstHandler, options: TranslateOptions = {}): TranslateResult { + const compiler = new TypeScriptCompiler(); + + return translateSnippet(source, compiler, visitor, options); +} + +function translateSnippet(source: Source, compiler: TypeScriptCompiler, visitor: AstHandler, options: TranslateOptions = {}): TranslateResult { + return source.withContents((filename, contents) => { + const result = compiler.compileInMemory(filename, contents); + + const converter = new AstConverter(result.rootFile, result.program.getTypeChecker(), visitor, options); + const converted = converter.convert(result.rootFile); + + return { + tree: converted, + diagnostics: converter.diagnostics + }; + }); +} + +export function printDiagnostics(diags: ts.Diagnostic[], stream: NodeJS.WritableStream) { + diags.forEach(d => printDiagnostic(d, stream)); +} + +export function printDiagnostic(diag: ts.Diagnostic, stream: NodeJS.WritableStream) { + const host = { + getCurrentDirectory() { return '.'; }, + getCanonicalFileName(fileName: string) { return fileName; }, + getNewLine() { return '\n'; } + }; + + const message = ts.formatDiagnosticsWithColorAndContext([diag], host); + stream.write(message); +} + +export function isErrorDiagnostic(diag: ts.Diagnostic) { + return diag.category === ts.DiagnosticCategory.Error; +} + +export interface TranslateResult { + tree: OTree; + diagnostics: ts.Diagnostic[]; +} diff --git a/packages/jsii-sampiler/lib/typescript/ast-utils.ts b/packages/jsii-sampiler/lib/typescript/ast-utils.ts new file mode 100644 index 0000000000..95cefee736 --- /dev/null +++ b/packages/jsii-sampiler/lib/typescript/ast-utils.ts @@ -0,0 +1,316 @@ +import ts = require('typescript'); + +export function stripCommentMarkers(comment: string, multiline: boolean) { + if (multiline) { + // The text *must* start with '/*' and end with '*/'. + // Strip leading '*' from every remaining line (first line because of '**', + // other lines because of continuations. + return comment.substring(2, comment.length - 2) + .replace(/^[ \t]+/g, '') // Strip all leading whitepace + .replace(/[ \t]+$/g, '') // Strip all trailing whitepace + .replace(/^[ \t]*\*[ \t]?/gm, ''); // Strip "* " from start of line + } else { + // The text *must* start with '//' + return comment.replace(/^\/\/[ \t]?/gm, ''); + } +} + +export function stringFromLiteral(expr: ts.Expression) { + if (ts.isStringLiteral(expr)) { + return expr.text; + } + return '???'; +} + +/** + * All types of nodes that can be captured using `nodeOfType`, and the type of Node they map to + */ +export type CapturableNodes = { + [ts.SyntaxKind.ImportDeclaration]: ts.ImportDeclaration, + [ts.SyntaxKind.VariableDeclaration]: ts.VariableDeclaration, + [ts.SyntaxKind.ExternalModuleReference]: ts.ExternalModuleReference, + [ts.SyntaxKind.NamespaceImport]: ts.NamespaceImport, + [ts.SyntaxKind.NamedImports]: ts.NamedImports, + [ts.SyntaxKind.ImportSpecifier]: ts.ImportSpecifier, + [ts.SyntaxKind.StringLiteral]: ts.StringLiteral, +}; + +export type AstMatcher = (nodes?: ts.Node[]) => A | undefined; + +/** + * Return AST children of the given node + * + * Difference with node.getChildren(): + * + * - node.getChildren() must take a SourceFile (will fail if it doesn't get it) + * and returns a mix of abstract and concrete syntax nodes. + * - This function function will ONLY return abstract syntax nodes. + */ +export function nodeChildren(node: ts.Node): ts.Node[] { + const ret = new Array(); + node.forEachChild(n => { ret.push(n); }); + return ret; +} + +/** + * Match a single node of a given type + * + * Capture name is first so that the IDE can detect eagerly that we're falling into + * that overload and properly autocomplete the recognized node types from CapturableNodes. + * + * Looks like SyntaxList nodes appear in the printed AST, but they don't actually appear + */ +export function nodeOfType(syntaxKind: ts.SyntaxKind, children?: AstMatcher): AstMatcher; +// tslint:disable-next-line:max-line-length +export function nodeOfType(capture: N, capturableNodeType: S, children?: AstMatcher): AstMatcher & {[key in N]: CapturableNodes[S]}>; +// tslint:disable-next-line:max-line-length +export function nodeOfType(syntaxKindOrCaptureName: ts.SyntaxKind | N, nodeTypeOrChildren?: S | AstMatcher, children?: AstMatcher): AstMatcher | AstMatcher { + const capturing = typeof syntaxKindOrCaptureName === 'string'; // Determine which overload we're in (SyntaxKind is a number) + + const realNext = (capturing ? children : nodeTypeOrChildren as AstMatcher) || DONE; + const realCapture = capturing ? syntaxKindOrCaptureName as N : undefined; + const realSyntaxKind = capturing ? nodeTypeOrChildren : syntaxKindOrCaptureName; + + return (nodes) => { + for (const node of nodes || []) { + if (node.kind === realSyntaxKind) { + const ret = realNext(nodeChildren(node)); + if (!ret) { continue; } + + if (realCapture) { + return Object.assign(ret, { [realCapture]: node as CapturableNodes[S] }) as any; + } + return ret; + } + } + return undefined; + }; +} + +export function anyNode(): AstMatcher<{}>; +export function anyNode(children: AstMatcher): AstMatcher; +export function anyNode(children?: AstMatcher): AstMatcher | AstMatcher<{}> { + const realNext = children || DONE; + return nodes => { + for (const node of nodes || []) { + const m = realNext(nodeChildren(node)); + if (m) { return m; } + } + return undefined; + }; +} + +// Does not capture deeper because how would we even represent that? +// tslint:disable-next-line:max-line-length +export function allOfType(s: S, name: N, children?: AstMatcher): AstMatcher<{[key in N]: Array}> { + type ArrayType = Array; + type ReturnType = {[key in N]: ArrayType}; + const realNext = children || DONE; + + return nodes => { + let ret: ReturnType | undefined; + for (const node of nodes || []) { + if (node.kind === s) { + if (realNext(nodeChildren(node))) { + if (!ret) { ret = { [name]: new Array() } as ReturnType; } + ret[name].push(node as any); + } + } + } + return ret; + }; +} + +export const DONE: AstMatcher<{}> = () => ({}); + +/** + * Run a matcher against a node and return (or invoke a callback with) the accumulated bindings + */ +export function matchAst(node: ts.Node, matcher: AstMatcher): A | undefined; +export function matchAst(node: ts.Node, matcher: AstMatcher, cb: (bindings: A) => void): boolean; +export function matchAst(node: ts.Node, matcher: AstMatcher, cb?: (bindings: A) => void): boolean | A | undefined { + const matched = matcher([node]); + if (cb) { + if (matched) { cb(matched); } + return !!matched; + } + return matched; +} + +/** + * Count the newlines in a given piece of string that aren't in comment blocks + */ +export function countNakedNewlines(str: string) { + let ret = 0; + scanText(str, 0, str.length) + .filter(s => s.type === 'other' || s.type === 'blockcomment') + .forEach(s => { + if (s.type === 'other') { + // Count newlines in non-comments + for (let i = s.pos; i < s.end; i++) { + if (str[i] === '\n') { ret++; } + } + } else { + // Discount newlines at the end of block comments + if (s.hasTrailingNewLine) { ret--; } + } + }); + return ret; +} + +export function repeatNewlines(str: string) { + return '\n'.repeat(Math.min(2, countNakedNewlines(str))); +} + +const WHITESPACE = [' ', '\t', '\r', '\n']; + +/** + * Extract single-line and multi-line comments from the given string + * + * Rewritten because I can't get ts.getLeadingComments and ts.getTrailingComments to do what I want. + */ +export function extractComments(text: string, start: number): ts.CommentRange[] { + return scanText(text, start) + .filter(s => s.type === 'blockcomment' || s.type === 'linecomment') + .map(commentRangeFromTextRange); +} + +export function commentRangeFromTextRange(rng: TextRange): ts.CommentRange { + return { + kind: rng.type === 'blockcomment' ? ts.SyntaxKind.MultiLineCommentTrivia : ts.SyntaxKind.SingleLineCommentTrivia, + pos: rng.pos, + end: rng.end, + hasTrailingNewLine: rng.hasTrailingNewLine + }; +} + +interface TextRange { + pos: number; + end: number; + type: 'linecomment' | 'blockcomment' | 'other'; + hasTrailingNewLine: boolean; +} + +/** + * Extract spans of comments and non-comments out of the string + * + * Stop at 'end' when given, or the first non-whitespace character in a + * non-comment if not given. + */ +export function scanText(text: string, start: number, end?: number): TextRange[] { + const ret: TextRange[] = []; + + let pos = start; + const stopAtCode = end === undefined; + if (end === undefined) { end = text.length; } + while (pos < end) { + const ch = text[pos]; + + if (WHITESPACE.includes(ch)) { pos++; continue; } + + if (ch === '/' && text[pos + 1] === '/') { + accumulateTextBlock(); + scanSinglelineComment(); + continue; + } + + if (ch === '/' && text[pos + 1] === '*') { + accumulateTextBlock(); + scanMultilineComment(); + continue; + } + + // Non-whitespace, non-comment, must be regular token. End if we're not scanning + // to a particular location, otherwise continue. + if (stopAtCode) { + break; + } + + pos++; + } + + accumulateTextBlock(); + + return ret; + + function scanMultilineComment() { + const endOfComment = findNext('*/', pos + 2); + ret.push({ + type: 'blockcomment', + hasTrailingNewLine: ['\n', '\r'].includes(text[endOfComment + 2]), + pos, + end: endOfComment + 2 + }); + pos = endOfComment + 2; + start = pos; + } + + function scanSinglelineComment() { + const nl = Math.min(findNext('\r', pos + 2), findNext('\n', pos + 2)); + ret.push({ + type: 'linecomment', + hasTrailingNewLine: true, + pos, + end: nl + }); + pos = nl + 1; + start = pos; + } + + function accumulateTextBlock() { + if (pos - start > 0) { + ret.push({ + type: 'other', + hasTrailingNewLine: false, + pos: start, + end: pos + }); + start = pos; + } + } + + function findNext(sub: string, startPos: number) { + const f = text.indexOf(sub, startPos); + if (f === -1) { return text.length; } + return f; + } +} + +const VOID_SHOW_KEYWORD = 'show'; + +export function extractMaskingVoidExpression(node: ts.Node): ts.VoidExpression | undefined { + const expr = extractVoidExpression(node); + if (!expr) { return undefined; } + if (ts.isStringLiteral(expr.expression) && expr.expression.text === VOID_SHOW_KEYWORD) { + return undefined; + } + return expr; +} + +export function extractShowingVoidExpression(node: ts.Node): ts.VoidExpression | undefined { + const expr = extractVoidExpression(node); + if (!expr) { return undefined; } + if (ts.isStringLiteral(expr.expression) && expr.expression.text === VOID_SHOW_KEYWORD) { + return expr; + } + return undefined; +} + +/** + * Return the string argument to a void expression if it exists + */ +export function voidExpressionString(node: ts.VoidExpression): string | undefined { + if (ts.isStringLiteral(node.expression)) { return node.expression.text; } + return undefined; +} + +/** + * We use void directives as pragmas. Extract the void directives here + */ +export function extractVoidExpression(node: ts.Node): ts.VoidExpression | undefined { + if (ts.isVoidExpression(node)) { return node; } + if (ts.isExpressionStatement(node)) { return extractVoidExpression(node.expression); } + if (ts.isParenthesizedExpression(node)) { return extractVoidExpression(node.expression); } + if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.CommaToken) { return extractVoidExpression(node.left); } + return undefined; +} diff --git a/packages/jsii-sampiler/lib/typescript/imports.ts b/packages/jsii-sampiler/lib/typescript/imports.ts new file mode 100644 index 0000000000..55970f355c --- /dev/null +++ b/packages/jsii-sampiler/lib/typescript/imports.ts @@ -0,0 +1,76 @@ +import ts = require('typescript'); +import { AstConverter } from '../converter'; +import { allOfType, matchAst, nodeOfType, stringFromLiteral } from "./ast-utils"; + +/** + * Our own unification of import statements + */ +export interface ImportStatement { + node: ts.Node; + packageName: string; + imports: FullImport | SelectiveImport; +} + +export type FullImport = { import: 'full', alias: string }; +export type SelectiveImport = { import: 'selective', elements: ImportBinding[] }; + +export interface ImportBinding { + sourceName: string; + alias?: string; +} + +export function analyzeImportEquals(node: ts.ImportEqualsDeclaration, context: AstConverter): ImportStatement { + let moduleName = '???'; + matchAst(node.moduleReference, + nodeOfType('ref', ts.SyntaxKind.ExternalModuleReference), + bindings => { + moduleName = stringFromLiteral(bindings.ref.expression); + }); + + return { + node, + packageName: moduleName, + imports: { import: 'full', alias: context.textOf(node.name) } + }; +} + +export function analyzeImportDeclaration(node: ts.ImportDeclaration, context: AstConverter): ImportStatement { + const packageName = stringFromLiteral(node.moduleSpecifier); + + const starBindings = matchAst(node, + nodeOfType(ts.SyntaxKind.ImportDeclaration, + nodeOfType(ts.SyntaxKind.ImportClause, + nodeOfType('namespace', ts.SyntaxKind.NamespaceImport)))); + + if (starBindings) { + return { + node, + packageName, + imports: { import: 'full', alias: context.textOf(starBindings.namespace.name) } + }; + } + + const namedBindings = matchAst(node, + nodeOfType(ts.SyntaxKind.ImportDeclaration, + nodeOfType(ts.SyntaxKind.ImportClause, + nodeOfType(ts.SyntaxKind.NamedImports, + allOfType(ts.SyntaxKind.ImportSpecifier, 'specifiers'))))); + + const elements: ImportBinding[] = []; + if (namedBindings) { + elements.push(...namedBindings.specifiers.map(spec => ( + // regular import { name }, renamed import { propertyName, name } + spec.propertyName ? { + sourceName: context.textOf(spec.propertyName), + alias: spec.name ? context.textOf(spec.name) : '???' + } : { + sourceName: spec.name ? context.textOf(spec.name) : '???' + }))); + } + + return { + node, + packageName, + imports: { import: 'selective', elements } + }; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/typescript/ts-compiler.ts b/packages/jsii-sampiler/lib/typescript/ts-compiler.ts new file mode 100644 index 0000000000..74397c1250 --- /dev/null +++ b/packages/jsii-sampiler/lib/typescript/ts-compiler.ts @@ -0,0 +1,85 @@ +import ts = require('typescript'); + +export class TypeScriptCompiler { + private readonly realHost: ts.CompilerHost; + + constructor() { + this.realHost = ts.createCompilerHost(STANDARD_COMPILER_OPTIONS, true); + } + + public createInMemoryCompilerHost(sourcePath: string, sourceContents: string): ts.CompilerHost { + const realHost = this.realHost; + const sourceFile = ts.createSourceFile(sourcePath, sourceContents, ts.ScriptTarget.Latest); + + return { + fileExists: filePath => filePath === sourcePath || realHost.fileExists(filePath), + directoryExists: realHost.directoryExists && realHost.directoryExists.bind(realHost), + getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost), + getDirectories: realHost.getDirectories && realHost.getDirectories.bind(realHost), + getCanonicalFileName: fileName => realHost.getCanonicalFileName(fileName), + getNewLine: realHost.getNewLine.bind(realHost), + getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), + getSourceFile: (fileName, languageVersion, onError, shouldCreateNewSourceFile) => fileName === sourcePath + ? sourceFile + : realHost.getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile), + readFile: filePath => filePath === sourcePath + ? sourceContents + : realHost.readFile(filePath), + useCaseSensitiveFileNames: () => realHost.useCaseSensitiveFileNames(), + writeFile(_fileName, _data) { /* nothing */ } + }; + } + + public compileInMemory(filename: string, contents: string): CompilationResult { + if (!filename.endsWith('.ts')) { + // Necessary or the TypeScript compiler won't compile the file. + filename += '.ts'; + } + + const program = ts.createProgram({ + rootNames: [filename], + options: STANDARD_COMPILER_OPTIONS, + host: this.createInMemoryCompilerHost(filename, contents), + }); + + const rootFiles = program.getSourceFiles().filter(f => f.fileName === filename); + if (rootFiles.length === 0) { + throw new Error(`Oopsie -- couldn't find root file back`); + } + const rootFile = rootFiles[0]; + + return { program, rootFile }; + } +} + +export interface CompilationResult { + program: ts.Program; + rootFile: ts.SourceFile; +} + +export const STANDARD_COMPILER_OPTIONS: ts.CompilerOptions = { + alwaysStrict: true, + charset: 'utf8', + declaration: true, + experimentalDecorators: true, + inlineSourceMap: true, + inlineSources: true, + lib: ['lib.es2016.d.ts', 'lib.es2017.object.d.ts', 'lib.es2017.string.d.ts'], + module: ts.ModuleKind.CommonJS, + noEmitOnError: true, + noFallthroughCasesInSwitch: true, + noImplicitAny: true, + noImplicitReturns: true, + noImplicitThis: true, + noUnusedLocals: true, + noUnusedParameters: true, + resolveJsonModule: true, + strict: true, + strictNullChecks: true, + strictPropertyInitialization: true, + stripInternal: true, + target: ts.ScriptTarget.ES2018, + // Incremental builds + incremental: true, + tsBuildInfoFile: '.tsbuildinfo', +}; \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/util.ts b/packages/jsii-sampiler/lib/util.ts new file mode 100644 index 0000000000..f4c79948a2 --- /dev/null +++ b/packages/jsii-sampiler/lib/util.ts @@ -0,0 +1,26 @@ +import fs = require('fs-extra'); +import os = require('os'); +import path = require('path'); +import { renderTree, Source, translateTypeScript } from '.'; +import { VisualizeAstVisitor } from './languages/visualize'; + +export function startsWithUppercase(x: string) { + return x.match(/^[A-Z]/); +} + +export function inTempDir(block: () => T): T { + const origDir = process.cwd(); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii')); + process.chdir(tmpDir); + const ret = block(); + process.chdir(origDir); + fs.removeSync(tmpDir); + return ret; +} + +export function visualizeTypeScriptAst(source: Source) { + const vis = translateTypeScript(source, new VisualizeAstVisitor(true), { + bestEffort: false + }); + return renderTree(vis.tree) + '\n'; +} diff --git a/packages/jsii-sampiler/package-lock.json b/packages/jsii-sampiler/package-lock.json new file mode 100644 index 0000000000..07a48d1e57 --- /dev/null +++ b/packages/jsii-sampiler/package-lock.json @@ -0,0 +1,4958 @@ +{ + "name": "jsii-sampiler", + "version": "0.18.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helpers": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/babel__core": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz", + "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/commonmark": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@types/commonmark/-/commonmark-0.27.4.tgz", + "integrity": "sha512-7koSjp08QxKoS1/+3T15+kD7+vqOUvZRHvM8PutF3Xsk5aAEkdlIGRsHJ3/XsC3izoqTwBdRW/vH7rzCKkIicA==", + "dev": true + }, + "@types/fs-extra": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz", + "integrity": "sha512-bCtL5v9zdbQW86yexOlXWTEGvLNqWxMFyi7gQA7Gcthbezr2cPSOb8SkESVKA937QD5cIwOFLDFt0MQoXOEr9Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.0.18", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.18.tgz", + "integrity": "sha512-jcDDXdjTcrQzdN06+TSVsPPqxvsZA/5QkYfIZlq1JMw7FdP5AZylbOc+6B/cuDurctRe+MziUMtQ3xQdrbjqyQ==", + "dev": true, + "requires": { + "@types/jest-diff": "*" + } + }, + "@types/jest-diff": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", + "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", + "dev": true + }, + "@types/node": { + "version": "12.6.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz", + "integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==", + "dev": true + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", + "dev": true + }, + "abab": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.1.tgz", + "integrity": "sha512-1zSbbCuoIjafKZ3mblY5ikvAb0ODUbqBnFuUb7f6uLeQhhGJ0vEV4ntmtxKLT2WgXCO94E07BjunsIw1jOMPZw==", + "dev": true + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.3.tgz", + "integrity": "sha512-vkR40VwS2SYO98AIeFvzWWh+xyc2qi9s7OoXSFEGIP/rOJKzjnhykaZJNnHdoq4BL2gGxI5EZOU16z896EYnOQ==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "dev": true, + "requires": { + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "bser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.0.tgz", + "integrity": "sha512-8zsjWrQkkBoLK6uxASk1nJ2SKv97ltiGDo6A3wA0/yRPz+CwmEyDo0hUrhIuukG2JHpAl3bvFIixw2/3Hi0DOg==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true, + "optional": true + }, + "commonmark": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.29.0.tgz", + "integrity": "sha512-Wc3kvAIm0EK85pHsM95Fev31wEN6/zQpwd2qcLDL8psjHRoUFvUeGHevIJAdToWUuFoX8WI/gmeDauqy32xgJQ==", + "requires": { + "entities": "~ 1.1.1", + "mdurl": "~ 1.0.1", + "minimist": "~ 1.2.0", + "string.prototype.repeat": "^0.2.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.1.tgz", + "integrity": "sha512-cp/Tb1oA/rh2X7vqeSOvM+TSo3UkJLX70eNihgVEvnzwAgikjkTFr/QVgRCaxjm0knCNQzNoxxxcw2zO2LJdZA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.0.0", + "string.prototype.trimright": "^2.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", + "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "exec-sh": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "handlebars": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", + "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hosted-git-info": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", + "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + } + }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" + }, + "dependencies": { + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "dev": true, + "requires": { + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" + }, + "dependencies": { + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + } + } + }, + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "dev": true, + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + }, + "dependencies": { + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "memory-streams": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/memory-streams/-/memory-streams-0.1.3.tgz", + "integrity": "sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA==", + "dev": true, + "requires": { + "readable-stream": "~1.0.2" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nwsapi": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "prompts": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.2.1.tgz", + "integrity": "sha512-VObPvJiWPhpZI6C5m60XOzTfnYg/xc/an+r9VYymj9WJW3B/DIH+REzjpAACPf8brwPeP+7vz3bIim3S+AaMjw==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.3" + } + }, + "psl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.1.tgz", + "integrity": "sha512-2KLd5fKOdAfShtY2d/8XDWVRnmp3zp40Qt6ge2zBPFARLXOGUf2fHD5eg+TV/5oxBtQKVhjUaKFsAaE4HnwfSA==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "react-is": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz", + "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sisteransi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.3.tgz", + "integrity": "sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string.prototype.repeat": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", + "integrity": "sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8=" + }, + "string.prototype.trimleft": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.0.0.tgz", + "integrity": "sha1-aLaqjhYsaoDnbjqKDC50cYbicf8=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimright": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.0.0.tgz", + "integrity": "sha1-q0pW2AKgH75yk+EehPJNyBZGYd0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typescript": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", + "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==" + }, + "uglify-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yargs": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz", + "integrity": "sha512-ssa5JuRjMeZEUjg7bEL99AwpitxU/zWGAGpdj0di41pOEmJti8NR6kyUIJBkR78DTYNPZOU08luUo0GTHuB+ow==", + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/packages/jsii-sampiler/package.json b/packages/jsii-sampiler/package.json new file mode 100644 index 0000000000..eb00fe262f --- /dev/null +++ b/packages/jsii-sampiler/package.json @@ -0,0 +1,45 @@ +{ + "name": "jsii-sampiler", + "version": "0.18.0", + "description": "Translate TypeScript code snippets to other languages", + "main": "lib/index.js", + "bin": { + "jsii-sampiler": "bin/jsii-sampiler" + }, + "scripts": { + "build": "tsc", + "test": "jest" + }, + "devDependencies": { + "@types/commonmark": "^0.27.4", + "@types/fs-extra": "^8.0.0", + "@types/jest": "^24.0.18", + "@types/node": "^12.6.8", + "@types/yargs": "^13.0.3", + "jest": "^24.9.0", + "memory-streams": "^0.1.3", + "typescript": "^3.5.3" + }, + "dependencies": { + "commonmark": "^0.29.0", + "fs-extra": "^8.1.0", + "typescript": "~3.6.2", + "yargs": "^14.0.0" + }, + "jest": { + "moduleFileExtensions": [ + "js" + ] + }, + "license": "Apache-2.0", + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/jsii.git", + "directory": "packages/jsii-sampiler" + } +} diff --git a/packages/jsii-sampiler/test/markdown/roundtrip.test.ts b/packages/jsii-sampiler/test/markdown/roundtrip.test.ts new file mode 100644 index 0000000000..5307b2576f --- /dev/null +++ b/packages/jsii-sampiler/test/markdown/roundtrip.test.ts @@ -0,0 +1,164 @@ +import { transformMarkdown } from "../../lib/markdown/markdown"; +import { MarkdownRenderer } from "../../lib/markdown/markdown-renderer"; +import { StructureRenderer } from "../../lib/markdown/structure-renderer"; + +const DEBUG = false; + +test('can roundtrip markdown', () => { + expectOutput(` +# Hello + +Yes please. + +> this +> +> works +`, ` +# Hello + +Yes please. + +> this +> +> works +`); +}); + +test('can roundtrip lists', () => { + expectOutput(` +* A list. +* Another list. + * A nested list. + +1. We might have numbers. +2. Yes it's a numbered list. + `, ` +* A list. +* Another list. + + * A nested list. + +1. We might have numbers. +2. Yes it's a numbered list. + `); +}); + +test('list with paragraphs', () => { + expectOutput(` +* A list. +* Another list. + + Para2. + `, ` +* A list. +* Another list. + + Para2. + `); +}); + +test('can roundtrip complex hyperlink texts', () => { + expectOutput(` +This is a [hyperlink](https://amazonaws.com). + +![Image though](fun.gif). + +This is a [` + '`' + `monospace hyperlink` + '`' + `](https://amazonaws.com). + `, ` +This is a [hyperlink](https://amazonaws.com). + +![Image though](fun.gif). + +This is a [` + '`' + `monospace hyperlink` + '`' + `](https://amazonaws.com). + `); +}); + +test('fenced code block', () => { + expectOutput([ + 'before', + '```ts', + 'banana', + ' second', + '```', + 'after', + ].join('\n'), [ + 'before', + '', + '```ts', + 'banana', + ' second', + '```', + '', + 'after', + ].join('\n')); +}); + +test('indented code block', () => { + expectOutput([ + 'before', + '', + ' banana', + ' second', + '', + 'after', + ].join('\n'), [ + 'before', + '', + '```', + 'banana', + ' second', + '```', + '', + 'after', + ].join('\n')); +}); + +test('code block followed by heading leaves paragraph marker', () => { + expectOutput([ + '```', + 'code_here', + '```', + '', + '# Heading', + ].join('\n'), [ + '```', + 'code_here', + '```', + '', + '# Heading', + ].join('\n')); +}); + +test('emphases', () => { + expectOutput(` +Text with *emphasis* and **strongness**. + +Other style _emphasis_ and __strongness__. + `, ` +Text with *emphasis* and **strongness**. + +Other style *emphasis* and **strongness**. + `); +}); + +test('headings', () => { + expectOutput(` +## Heading 2 +### Heading 3 + `, ` +## Heading 2 + +### Heading 3 + `); +}); + +function expectOutput(source: string, expected: string) { + if (DEBUG) { + const struct = new StructureRenderer(); + // tslint:disable-next-line:no-console + console.log(transformMarkdown(source, struct)); + } + + const output = transformMarkdown(source, new MarkdownRenderer()); + expect(output.trim()).toEqual(expected.trim()); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/test/otree.test.ts b/packages/jsii-sampiler/test/otree.test.ts new file mode 100644 index 0000000000..1763c18e6e --- /dev/null +++ b/packages/jsii-sampiler/test/otree.test.ts @@ -0,0 +1,50 @@ +import { OTree, renderTree } from "../lib/o-tree"; + +test('test indentation', () => { + const tree = new OTree(['{'], + ['\na', '\nb', '\nc'], + { + separator: ', ', + indent: 4, + suffix: '\n}', + }); + + expect(renderTree(tree)).toEqual('{\n a,\n b,\n c\n}'); +}); + +test('collapse subsequent unused indentation', () => { + const tree = new OTree(['{'], + [new OTree([], ['\na', '\nb', '\nc'], { indent: 4, separator: ', ' })], + { + separator: ', ', + indent: 4, + suffix: '\n}', + }); + + expect(renderTree(tree)).toEqual('{\n a,\n b,\n c\n}'); +}); + +test('don not collapse subsequent USED indentation', () => { + const tree = new OTree(['{'], + [ + '\na', + new OTree(['\n{'], ['\na', '\nb', '\nc'], { indent: 4, separator: ', ', suffix: '\n}' }), + '\nb', + ], + { + separator: ', ', + indent: 4, + suffix: '\n}', + }); + + expect(renderTree(tree)).toEqual([ + '{', + ' a,', + ' {', + ' a,', + ' b,', + ' c', + ' },', + ' b', + '}'].join('\n')); +}); diff --git a/packages/jsii-sampiler/test/python/calls.test.ts b/packages/jsii-sampiler/test/python/calls.test.ts new file mode 100644 index 0000000000..14dfe7a163 --- /dev/null +++ b/packages/jsii-sampiler/test/python/calls.test.ts @@ -0,0 +1,197 @@ +import { expectPython } from "./python"; + +test('function call', async () => { + expectPython(` + callSomeFunction(1, 2, 3); + `, ` + call_some_function(1, 2, 3) + `); +}); + +test('method call', async () => { + expectPython(` + someObject.callSomeFunction(1, 2, 3); + `, ` + some_object.call_some_function(1, 2, 3) + `); +}); + +test('static function call', async () => { + expectPython(` + SomeObject.callSomeFunction(1, 2, 3); + `, ` + SomeObject.call_some_function(1, 2, 3) + `); +}); + +test('translate this to self when calling', async () => { + expectPython(` + callSomeFunction(this, 25); + `, ` + call_some_function(self, 25) + `); +}); + +test('translate this to self on LHS of object accessor', async () => { + expectPython(` + this.callSomeFunction(25); + `, ` + self.call_some_function(25) + `); +}); + +test('translate object literals in function call', async () => { + expectPython(` + foo(25, { foo: 3, banana: "hello" }); + `, ` + foo(25, foo=3, banana="hello") + `); +}); + +test('translate object literals with newlines', async () => { + expectPython(` + foo(25, { + foo: 3, + banana: "hello" + }); + `, ` + foo(25, + foo=3, + banana="hello" + ) + `); +}); + +test('translate object literals with multiple newlines', async () => { + expectPython(` + foo(25, { + foo: 3, + + banana: "hello" + }); + `, ` + foo(25, + foo=3, + + banana="hello" + ) + `); +}); + +test('translate object literals only one level deep', async () => { + // FIXME: This is wrong! We need the types here! + expectPython(` + foo(25, { foo: 3, deeper: { a: 1, b: 2 }); + `, ` + foo(25, foo=3, deeper={"a": 1, "b": 2}) + `); +}); + +test('translate object literals second level with newlines', async () => { + expectPython(` + foo(25, { foo: 3, deeper: { + a: 1, + b: 2 + }); + `, ` + foo(25, foo=3, deeper={ + "a": 1, + "b": 2 + }) + `); +}); + +test('will type deep structs directly if type info is available', () => { + expectPython(` + interface BaseDeeperStruct { + a: number; + } + interface DeeperStruct extends BaseDeeperStruct { + b: number; + } + + interface OuterStruct { + foo: number; + deeper: DeeperStruct; + } + + function foo(x: number, outer: OuterStruct) { } + + foo(25, { foo: 3, deeper: { + a: 1, + b: 2 + }); + `, ` + def foo(x, *, foo, deeper): + pass + + foo(25, foo=3, deeper=DeeperStruct( + a=1, + b=2 + )) + `); +}); + +test('default arguments get =None appended', () => { + expectPython(` + function foo(x: string | undefined, y: string = 'hello', z?: string) { + console.log(x, y, z); + } + `, ` + def foo(x=None, y=None, z=None): + print(x, y, z) + `); +}); + +test('default struct fields get =None appended', () => { + expectPython(` + interface Struct { + x: string | undefined; + y?: string; + } + function foo(s: Struct) { + console.log(s.x, s.y); + } + `, ` + def foo(*, x=None, y=None): + print(x, y) + `); +}); + +test('list of structs', () => { + expectPython(` + foo({ + list: [{ + a: 1, + b: 2 + }, { + a: 3, + b: 4, + }] + }); + `, ` + foo( + list=[{ + "a": 1, + "b": 2 + }, { + "a": 3, + "b": 4 + }] + ) + `); +}); + +test('literal map argument doesnt get keyworded', () => { + // requires type information to work + expectPython(` + function foo(xs: {[key: string]: string}) { } + + foo({ foo: 'bar', schmoo: 'schmar' }) + `, ` + def foo(xs): + pass + + foo({"foo": "bar", "schmoo": "schmar"}) + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/classes.test.ts b/packages/jsii-sampiler/test/python/classes.test.ts new file mode 100644 index 0000000000..10571b3d53 --- /dev/null +++ b/packages/jsii-sampiler/test/python/classes.test.ts @@ -0,0 +1,166 @@ +import { expectPython } from "./python"; + +test('class declaration with fields and constructor', async () => { + // FIXME: This whitespace is not entirely correct, but it's not horrible + // and I don't know how to fix it for now. + expectPython(` + class MyClass { + private readonly x: string; + + constructor(y: string) { + this.x = y; + } + } + `, ` + class MyClass: + + def __init__(self, y): + self.x = y + `); +}); + +test('whitespace between multiple members', () => { + expectPython(` + class MyClass { + constructor(y: string) { + this.x = y; + } + + public hello() { + console.log(this.x); + } + + public bye() { + console.log('bye'); + } + } + `, ` + class MyClass: + def __init__(self, y): + self.x = y + + def hello(self): + print(self.x) + + def bye(self): + print("bye") + `); +}); + +test('whitespace between multiple empty members', () => { + expectPython(` + class MyClass { + constructor(y: string) { + this.x = y; + } + + public hello() { + } + + public bye() { + } + } + `, ` + class MyClass: + def __init__(self, y): + self.x = y + + def hello(self): + pass + + def bye(self): + pass + `); +}); + +test('invisible interfaces do not affect whitespace', async () => { + expectPython(` + class MyClass1 { + } + + interface ThisWillNotBeRendered { + } + + class MyClass2 { + } + `, ` + class MyClass1: + pass + + class MyClass2: + pass + `); +}); + +test.skip('class with implicit declaration', async () => { + expectPython(` + class MyClass { + private readonly x = 'bloep'; + } + `, ` + class MyClass: + def __init__(self): + self.x = 'bloep' + `); +}); + +test('class with inheritance', async () => { + expectPython(` + class MyClass extends cdk.SomeOtherClass { + } + `, ` + class MyClass(cdk.SomeOtherClass): + pass + `); +}); + +test('class with inheritance and super class', async () => { + expectPython(` + class MyClass extends cdk.SomeOtherClass { + constructor(x: string, y: string) { + super(x); + } + } + `, ` + class MyClass(cdk.SomeOtherClass): + def __init__(self, x, y): + super().__init__(x) + `); +}); + +test('class with method', async () => { + expectPython(` + class MyClass extends cdk.SomeOtherClass { + public someMethod(x: string) { + console.log(x); + } + } + `, ` + class MyClass(cdk.SomeOtherClass): + def some_method(self, x): + print(x) + `); +}); + +test('class with props argument', async () => { + expectPython(` + interface MyClassProps { + readonly prop1: string; + readonly prop2: number; + } + + class MyClass extends cdk.SomeOtherClass { + constructor(scope: cdk.Construct, id: string, props: MyClassProps) { + super(scope, id, props); + + print(props.prop1); + } + } + `, ` + class MyClass(cdk.SomeOtherClass): + def __init__(self, scope, id, *, prop1, prop2): + super().__init__(scope, id, prop1=prop1, prop2=prop2) + + print(prop1) + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/comments.test.ts b/packages/jsii-sampiler/test/python/comments.test.ts new file mode 100644 index 0000000000..1fd2ecb011 --- /dev/null +++ b/packages/jsii-sampiler/test/python/comments.test.ts @@ -0,0 +1,84 @@ +import { expectPython } from "./python"; + +test('interleave single line comments with function call', () => { + expectPython(` + someFunction(arg1, { + // A comment before arg2 + arg2: 'string', + + // A comment before arg3 + arg3: 'boo' + }); + `, ` + some_function(arg1, + # A comment before arg2 + arg2="string", + + # A comment before arg3 + arg3="boo" + ) + `); +}); + +test('interleave multiline comments with function call', () => { + expectPython(` + someFunction(arg1, { + /* A comment before arg2 */ + arg2: 'string', + + /* A comment before arg3 */ + arg3: 'boo' + }); + `, ` + some_function(arg1, + # A comment before arg2 + arg2="string", + + # A comment before arg3 + arg3="boo" + ) + `); +}); + +test('no duplication of comments', () => { + // Harder than it looks! + expectPython(` + // Here's a comment + object.member.functionCall(new Class(), "argument"); + `, ` + # Here's a comment + object.member.function_call(Class(), "argument") + `); +}); + +test('empty lines in comments', () => { + expectPython(` + // Here's a comment + // + // Second line + someCall(); + `, ` + # Here's a comment + # + # Second line + some_call() + `); +}); + +test.skip('trailing comments', () => { + expectPython(` + someCall(); // Oh no, it's a call + + otherCall({ + value: 5, // That's a big number + secondValue: 6 // Even bigger + }); + `, ` + some_call() # Oh no, it's a call + + other_call( + value=5, # That's a big number + second_value=6 # Even bigger + ) + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/expressions.test.ts b/packages/jsii-sampiler/test/python/expressions.test.ts new file mode 100644 index 0000000000..1694927696 --- /dev/null +++ b/packages/jsii-sampiler/test/python/expressions.test.ts @@ -0,0 +1,61 @@ +import { expectPython } from "./python"; + +test('as-expression', () => { + expectPython(` + console.log(3 as number); + `, ` + print(3) + `); +}); + +test('prefix unary expression', () => { + expectPython(` + console.log(-3); + `, ` + print(-3) + `); +}); + +test('ellipsis at a random place', () => { + expectPython(` + callThisFunction(foo, ...); + `, ` + call_this_function(foo, ...) + `); +}); + +test('string interpolation', () => { + expectPython([ + 'const x = "world";', + 'const y = "well";', + 'console.log(`Hello, ${x}, it works ${y}!`);', + ].join('\n'), ` + x = "world" + y = "well" + print(f"Hello, {x}, it works {y}!") + `); +}); + +test('non-null expression', () => { + expectPython([ + 'const x = someObject!.someAttribute;', + ].join('\n'), ` + x = some_object.some_attribute + `); +}); + +test('double-quoted dict keys', () => { + expectPython([ + 'const x = { "key": "value" }', + ].join('\n'), ` + x = {"key": "value"} + `); +}); + +test('backtick string w/o substitutions', () => { + expectPython([ + 'const x = `some string`', + ].join('\n'), ` + x = "some string" + `); +}); diff --git a/packages/jsii-sampiler/test/python/hiding.test.ts b/packages/jsii-sampiler/test/python/hiding.test.ts new file mode 100644 index 0000000000..76dd0e1a7b --- /dev/null +++ b/packages/jsii-sampiler/test/python/hiding.test.ts @@ -0,0 +1,60 @@ +import { expectPython } from "./python"; + +test('hide top level statements using void directive', () => { + expectPython(` + void 1; + function foo(x: number) { + } + void 'show'; + foo(3); + `, ` + foo(3) + `); +}); + +test('hide block level statements using void directive', () => { + expectPython(` + if (true) { + console.log('everything is well'); + void 1; + subprocess.exec('rm -rf /'); + } + + onlyToEndOfBlock(); + `, ` + if True: + print("everything is well") + + only_to_end_of_block() + `); +}); + +test('hide parameter sequence', () => { + expectPython(` + foo(3, (void 1, 4), 5, 6, (void 'show', 7), 8); + `, ` + foo(3, 8) + `); +}); + +test('hide expression with explicit ellipsis', () => { + expectPython(` + foo(3, (void '...', 4), 5, 6, 7); + `, ` + foo(3, ...) + `); +}); + +test('hide statements with explicit ellipsis', () => { + expectPython(` + before(); + void 'block'; + middle(); + void 'show'; + after(); + `, ` + before() + # ... + after() + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/imports.test.ts b/packages/jsii-sampiler/test/python/imports.test.ts new file mode 100644 index 0000000000..6ac8e0bbbe --- /dev/null +++ b/packages/jsii-sampiler/test/python/imports.test.ts @@ -0,0 +1,26 @@ + +import { expectPython } from "./python"; + +test('import/require', async () => { + await expectPython(` + import mod = require('@scope/some-module'); + `, ` + import scope.some_module as mod + `); +}); + +test('import star-as', async () => { + await expectPython(` + import * as mod from '@scope/some-module'; + `, ` + import scope.some_module as mod + `); +}); + +test('selective import', async () => { + await expectPython(` + import { one, Two, someThree, four as renamed } from '@scope/some-module'; + `, ` + from scope.some_module import one, Two, some_three, four as renamed + `); +}); diff --git a/packages/jsii-sampiler/test/python/misc.test.ts b/packages/jsii-sampiler/test/python/misc.test.ts new file mode 100644 index 0000000000..3639e91b66 --- /dev/null +++ b/packages/jsii-sampiler/test/python/misc.test.ts @@ -0,0 +1,9 @@ +import { expectPython } from "./python"; + +test('booleans render to right primitives', () => { + expectPython(` + callFunction(true, false); + `, ` + call_function(True, False) + `); +}); diff --git a/packages/jsii-sampiler/test/python/python.ts b/packages/jsii-sampiler/test/python/python.ts new file mode 100644 index 0000000000..4a92989a10 --- /dev/null +++ b/packages/jsii-sampiler/test/python/python.ts @@ -0,0 +1,42 @@ +import { LiteralSource, renderTree, translateTypeScript } from "../../lib"; +import { PythonVisitor } from "../../lib/languages/python"; +import { visualizeTypeScriptAst } from "../../lib/util"; + +const DEBUG = false; + +export function ts2python(source: string): string { + const src = new LiteralSource(source, 'test.ts'); + + if (DEBUG) { + // tslint:disable-next-line:no-console + console.log(visualizeTypeScriptAst(src)); + } + const result = translateTypeScript(src, new PythonVisitor()); + + // Very debug. Much print. + // console.log(JSON.stringify(result.tree, undefined, 2)); + + return renderTree(result.tree) + '\n'; +} + +export function expectPython(source: string, expected: string) { + expect(stripEmptyLines(ts2python(source))).toEqual(stripEmptyLines(stripCommonWhitespace(expected))); +} + +function stripCommonWhitespace(x: string) { + const lines = x.split('\n'); + const whitespaces = lines.filter(l => !emptyLine(l.trim())).map(l => l.match(/(\s*)/)![1].length); + const minWS = Math.min(...whitespaces); + return lines.map(l => l.substr(minWS)).join('\n'); +} + +function stripEmptyLines(x: string) { + const lines = x.split('\n'); + while (lines.length > 0 && emptyLine(lines[0])) { lines.splice(0, 1); } + while (lines.length > 0 && emptyLine(lines[lines.length - 1])) { lines.pop(); } + return lines.join('\n'); +} + +function emptyLine(x: string) { + return x.trim() === ''; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/statements.test.ts b/packages/jsii-sampiler/test/python/statements.test.ts new file mode 100644 index 0000000000..99d1b610bd --- /dev/null +++ b/packages/jsii-sampiler/test/python/statements.test.ts @@ -0,0 +1,113 @@ +import { expectPython } from "./python"; +import { LiteralSource, PythonVisitor, translateTypeScript, renderTree } from "../../lib"; + +test('if', () => { + expectPython(` + if (x == 3) { + console.log('bye'); + } + `, ` + if x == 3: + print("bye") + `); +}); + +test('if/then/else', () => { + expectPython(` + if (x == 3) { + console.log('bye'); + } else { + console.log('toodels'); + } + `, ` + if x == 3: + print("bye") + else: + print("toodels") + `); +}); + +test('multiline if/then/else', () => { + expectPython(` + if (x == 3) { + x += 1; + console.log('bye'); + } else { + console.log('toodels'); + } + `, ` + if x == 3: + x += 1 + print("bye") + else: + print("toodels") + `); +}); + +test('empty control block', () => { + expectPython(` + if (x == 3) { + } + `, ` + if x == 3: + pass + `); +}); + +test('block without braces', () => { + expectPython(` + if (x == 3) console.log('hello'); + `, ` + if x == 3: print("hello") + `); +}); + +test('for/of loop', () => { + expectPython(` + for (const x of xs) { + console.log(x); + } + `, ` + for x in xs: + print(x) + `); +}); + +test('whitespace between statements', () => { + expectPython(` + statementOne(); + + statementTwo(); + `, ` + statement_one() + + statement_two() + `); +}); + +test('whitespace between statements in a block', () => { + expectPython(` + if (condition) { + statementOne(); + + statementTwo(); + } + `, ` + if condition: + statement_one() + + statement_two() + `); +}); + +test('prepend disclaimer', () => { + const src = new LiteralSource('console.log("hello");', 'test.ts'); + + const result = translateTypeScript(src, new PythonVisitor({ + disclaimer: 'Do not write this code' + })); + + expect(renderTree(result.tree)).toEqual( +`# Do not write this code +print("hello")`); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/tsconfig.json b/packages/jsii-sampiler/tsconfig.json new file mode 100644 index 0000000000..3dd58625bc --- /dev/null +++ b/packages/jsii-sampiler/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2018", + "module": "commonjs", + "lib": ["es2016", "es2017.object", "es2017.string"], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "strictPropertyInitialization": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "composite": true + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "examples" + ] +} diff --git a/packages/jsii-spec/package-lock.json b/packages/jsii-spec/package-lock.json index 05e06b9fa9..dc54a217cf 100644 --- a/packages/jsii-spec/package-lock.json +++ b/packages/jsii-spec/package-lock.json @@ -3711,10 +3711,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", diff --git a/packages/jsii/lib/helpers.ts b/packages/jsii/lib/helpers.ts index d0079bb07c..48696c81f3 100644 --- a/packages/jsii/lib/helpers.ts +++ b/packages/jsii/lib/helpers.ts @@ -44,7 +44,7 @@ async function inTempDir(block: () => Promise): Promise { process.chdir(tmpDir); const ret = await block(); process.chdir(origDir); - // await fs.remove(tmpDir); + await fs.remove(tmpDir); return ret; } diff --git a/packages/jsii/package-lock.json b/packages/jsii/package-lock.json index 6b6d77249b..dde3f3458a 100644 --- a/packages/jsii/package-lock.json +++ b/packages/jsii/package-lock.json @@ -3679,18 +3679,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3738,11 +3726,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", diff --git a/packages/oo-ascii-tree/package-lock.json b/packages/oo-ascii-tree/package-lock.json index 427e41e60a..7cc5f28df6 100644 --- a/packages/oo-ascii-tree/package-lock.json +++ b/packages/oo-ascii-tree/package-lock.json @@ -3558,10 +3558,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",