diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1d06437 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +insert_final_newline = true +tab_width = 4 +trim_trailing_whitespace = true + +[*.json] +insert_final_newline = false + +[*.{gif,gitignore,html,jpeg,jpg,md,png,svg,vscodeignore}] +insert_final_newline = false +trim_trailing_whitespace = false + +[LICENSE] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.vscodeignore b/.vscodeignore index cf47569..16d0fc9 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,15 +1,16 @@ -.vscode/** -typings/** -out/test/** -test/** -src/** **/*.map -.gitignore -images/**/*.gif +.vscode/** documentation/** !documentation/examples/* !documentation/images/* !documentation/documentation.html +images/**/*.gif +out/test/** +src/** +typings/** +test/** +.editorconfig +.gitignore +ISSUE_TEMPLATE.md tsconfig.json -vsc-extension-quickstart.md tslint.json \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f0cefaa..c11d2ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to the "mjml" extension will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). +### [1.6.0] (2018-10-28) +* [new] Configuration property `mjml.templateGallery`: Show the template gallery instead of quick pick. +* [new] Configuration property `mjml.templateGalleryAutoClose`: Automatically close template gallery when selecting a template. +* [#42](https://github.com/attilabuti/vscode-mjml/issues/42) [#43](https://github.com/attilabuti/vscode-mjml/issues/43): fixed beautify issues. +* [new] [#47](https://github.com/attilabuti/vscode-mjml/issues/47) `MJML: Version`: Shows the version of MJML. +* .mjmlconfig is working again. +* MJML 4.2.0 +* Other improvements and bugfixes. + ### [1.5.1] (2018-10-03) * [#41](https://github.com/attilabuti/vscode-mjml/issues/41): fixed preview issue. * [#40](https://github.com/attilabuti/vscode-mjml/issues/40): fixed comment issue. diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..79e80dc --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,35 @@ +Before you open an issue, please check if a similar issue already exists or has been closed before. + +## Expected behavior + +Please provide a description of the behavior you expect. + +## Actual behavior + +Please provide a description of the actual behavior you observe. + +## Steps to reproduce the problem + + 1. + 1. + 1. + +## Code sample + +``` +Please provide a code snippet. +``` + +## Screenshot / GIF + +Please attach screenshot/gif if you consider them as helpful to understand/reproduce the issue. + +## Specifications + + - VS Code version: + - MJML extension version: + - Operating system and version: + +## Other information + +List any other information that is relevant to your issue. \ No newline at end of file diff --git a/README.md b/README.md index 0aec34c..830f808 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ The following command is available: * **MJML: Template** Fetch official templates. * **MJML: Documentation** open the MJML documentation. * **MJML: Search in MJML documentation** search for the selected mj-element in the MJML documentation. +* **MJML: Version** Shows the version of MJML. ## Settings @@ -78,6 +79,8 @@ The following command is available: | `mjml.previewBackgroundColor` | ` ` | Preview background color. | | `mjml.autoClosePreview` | `true` | Automatically close preview when all open MJML documents have been closed. | | `mjml.showSaveDialog` | `false` | Show the save as dialog instead of input box. | +| `mjml.templateGallery` | `false` | Show the template gallery instead of quick pick. | +| `mjml.templateGalleryAutoClose` | `true` | Automatically close template gallery when selecting a template. | ## Snippets @@ -159,6 +162,15 @@ Please see the [Nodemailer](https://nodemailer.com) documentation for more infor ## Change Log +### [1.6.0] (2018-10-28) +* [new] Configuration property `mjml.templateGallery`: Show the template gallery instead of quick pick. +* [new] Configuration property `mjml.templateGalleryAutoClose`: Automatically close template gallery when selecting a template. +* [#42](https://github.com/attilabuti/vscode-mjml/issues/42) [#43](https://github.com/attilabuti/vscode-mjml/issues/43): fixed beautify issues. +* [new] [#47](https://github.com/attilabuti/vscode-mjml/issues/47) `MJML: Version`: Shows the version of MJML. +* .mjmlconfig is working again. +* MJML 4.2.0 +* Other improvements and bugfixes. + ### [1.5.1] (2018-10-03) * [#41](https://github.com/attilabuti/vscode-mjml/issues/41): fixed preview issue. * [#40](https://github.com/attilabuti/vscode-mjml/issues/40): fixed comment issue. diff --git a/documentation/build.ts b/documentation/build.ts index f176e8d..17d5a92 100644 --- a/documentation/build.ts +++ b/documentation/build.ts @@ -3,8 +3,8 @@ import * as fs from "fs"; import * as path from "path"; -import * as fetch from "node-fetch"; import * as hljs from "highlight.js"; +import * as fetch from "node-fetch"; const md = require("markdown-it")({ html: true, @@ -247,4 +247,4 @@ async function tryItLive(html: string): Promise { return html; } -run(); \ No newline at end of file +run(); diff --git a/package-lock.json b/package-lock.json index ba29a05..9c17ce2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,26 +1,18 @@ { "name": "vscode-mjml", - "version": "1.5.1", + "version": "1.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { - "@types/commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==", - "requires": { - "commander": "2.18.0" - } - }, "@types/copy-paste": { "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@types/copy-paste/-/copy-paste-1.1.30.tgz", + "resolved": "http://registry.npmjs.org/@types/copy-paste/-/copy-paste-1.1.30.tgz", "integrity": "sha1-p9RUyeHkVCMo9/Huz1Mzvoz7UO0=", "dev": true }, "@types/events": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", "dev": true }, @@ -30,10 +22,10 @@ "integrity": "sha512-9YqUM3izkmwtCbq6ANdcHJiU2mpDvPm3WuHOcJ5ZouHw7CoYcyY/KvZm6dmYTIurfrRsmBIvHr6y1jpBjDd4Jg==", "dev": true }, - "@types/is-url": { - "version": "1.2.28", - "resolved": "https://registry.npmjs.org/@types/is-url/-/is-url-1.2.28.tgz", - "integrity": "sha1-kU2r1QVG2bAUKAbkLHK8fCt+B4c=", + "@types/js-beautify": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/js-beautify/-/js-beautify-1.8.0.tgz", + "integrity": "sha512-/siF86XrwDKLuHe8l7h6NhrAWgLdgqbxmjZv9NvGWmgYRZoTipkjKiWb0SQHy/jcR+ee0GvbG6uGd+LEBMGNvA==", "dev": true }, "@types/mime": { @@ -43,10 +35,18 @@ "dev": true }, "@types/node": { - "version": "10.11.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.11.3.tgz", - "integrity": "sha512-3AvcEJAh9EMatxs+OxAlvAEs7OTy6AG94mcH1iqyVDwVVndekLxzwkWQ/Z4SDbY6GO2oyUXyWW8tQ4rENSSQVQ==", - "dev": true + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", + "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==" + }, + "@types/node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha512-XroxUzLpKuL+CVkQqXlffRkEPi4Gh3Oui/mWyS7ztKiyqVxiU+h3imCW5I2NQmde5jK+3q++36/Q96cyRWsweg==", + "dev": true, + "requires": { + "@types/node": "10.12.0" + } }, "@types/nodemailer": { "version": "4.6.5", @@ -55,7 +55,7 @@ "dev": true, "requires": { "@types/events": "1.2.0", - "@types/node": "10.11.3" + "@types/node": "10.12.0" } }, "@types/npm": { @@ -64,7 +64,7 @@ "integrity": "sha512-McqGDdeT1tSMu8sPaL0ya7xBwojQYKGVwCrlPNBcaF+o+H4wLNH03nYRTfycU11Xdu8eziEb4cgdGmu4VF/NWA==", "dev": true, "requires": { - "@types/node": "10.11.3" + "@types/node": "10.12.0" } }, "@types/semver": { @@ -72,17 +72,6 @@ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==" }, - "ab-webshot": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ab-webshot/-/ab-webshot-1.0.0.tgz", - "integrity": "sha512-GykorxI3AZ4fqdhFiyxkcgJCwnkr53IyWcb58riSIdytnXa+EwcMOaqZS+eXztBigpa54JIUr/ocLvADNhzVQQ==", - "requires": { - "cross-spawn": "6.0.5", - "graceful-fs": "4.1.11", - "phantomjs-prebuilt": "2.1.16", - "tmp": "0.0.33" - } - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -234,9 +223,9 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, "ast-types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.6.tgz", + "integrity": "sha512-nHiuV14upVGl7MWwFUYbzJ6YlfwWS084CU9EA8HajfYQjMSli5TQi3UTRygGF58LFWVkXxS1rbgRhROEqlQkXg==" }, "async": { "version": "2.6.1", @@ -271,6 +260,25 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + } + } + }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", @@ -349,7 +357,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "optional": true, "requires": { "tweetnacl": "0.14.5" } @@ -485,13 +492,13 @@ }, "cheerio": { "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "resolved": "http://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", "requires": { "css-select": "1.2.0", "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.9.2", + "entities": "1.1.2", + "htmlparser2": "3.10.0", "lodash.assignin": "4.2.0", "lodash.bind": "4.2.1", "lodash.defaults": "4.2.0", @@ -604,6 +611,23 @@ "inherits": "2.0.3", "process-nextick-args": "2.0.0", "readable-stream": "2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "co": { @@ -625,6 +649,56 @@ "object-visit": "1.0.1" } }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "1.9.3", + "color-string": "1.5.3" + } + }, + "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=" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, + "colors": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==" + }, + "colorspace": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", + "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", + "requires": { + "color": "3.0.0", + "text-hex": "1.0.0" + } + }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -634,9 +708,9 @@ } }, "commander": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", - "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==" + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" }, "component-emitter": { "version": "1.2.1", @@ -652,12 +726,27 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "optional": true, "requires": { "buffer-from": "1.1.1", "inherits": "2.0.3", "readable-stream": "2.3.6", "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "config-chain": { @@ -723,26 +812,26 @@ "requires": { "nice-try": "1.0.5", "path-key": "2.0.1", - "semver": "5.5.1", + "semver": "5.6.0", "shebang-command": "1.2.0", "which": "1.3.1" } }, "css-select": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "requires": { "boolbase": "1.0.0", - "css-what": "2.1.0", + "css-what": "2.1.2", "domutils": "1.5.1", - "nth-check": "1.0.1" + "nth-check": "1.0.2" } }, "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz", + "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==" }, "dashdash": { "version": "1.14.1", @@ -764,7 +853,7 @@ "requires": { "image-size": "0.6.3", "mimer": "0.3.2", - "semver": "5.5.1" + "semver": "5.6.0" } }, "debug": { @@ -856,7 +945,7 @@ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", "requires": { - "ast-types": "0.11.5", + "ast-types": "0.11.6", "escodegen": "1.11.0", "esprima": "3.1.3" } @@ -871,10 +960,20 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "requires": { + "colorspace": "1.1.1", + "enabled": "1.0.2", + "kuler": "1.0.1" + } + }, "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "dom-serializer": { @@ -883,27 +982,27 @@ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", "requires": { "domelementtype": "1.1.3", - "entities": "1.1.1" + "entities": "1.1.2" }, "dependencies": { "domelementtype": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" } } }, "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.2.1.tgz", + "integrity": "sha512-SQVCLFS2E7G5CRCMdn6K9bIhRj1bS6QBWZfF0TUPh4V/BbqrQ619IdSS3/izn0FZ+9l+uODzaZjb08fjOfablA==" }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "requires": { - "domelementtype": "1.3.0" + "domelementtype": "1.2.1" } }, "domutils": { @@ -912,7 +1011,7 @@ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "requires": { "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" + "domelementtype": "1.2.1" } }, "duplexer": { @@ -922,40 +1021,64 @@ "dev": true }, "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", "dev": true, "requires": { "end-of-stream": "1.4.1", "inherits": "2.0.3", "readable-stream": "2.3.6", "stream-shift": "1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "optional": true, "requires": { "jsbn": "0.1.1", "safer-buffer": "2.1.2" } }, "editorconfig": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.0.tgz", - "integrity": "sha512-j7JBoj/bpNzvoTQylfRZSc85MlLNKWQiq5y6gwKhmqD2h1eZ+tH4AXbkhEJD468gjDna/XMx2YtSkCxBRX9OGg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.2.tgz", + "integrity": "sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ==", "requires": { - "@types/commander": "2.12.2", + "@types/node": "10.12.0", "@types/semver": "5.5.0", - "commander": "2.18.0", + "commander": "2.19.0", "lru-cache": "4.1.3", - "semver": "5.5.1", + "semver": "5.6.0", "sigmund": "1.0.1" } }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "requires": { + "env-variable": "0.0.5" + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -966,9 +1089,14 @@ } }, "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "env-variable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", + "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" }, "error-ex": { "version": "1.3.2", @@ -985,7 +1113,7 @@ }, "es6-promisify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "requires": { "es6-promise": "4.2.5" @@ -1030,7 +1158,7 @@ "dev": true, "requires": { "duplexer": "0.1.1", - "flatmap-stream": "0.1.0", + "flatmap-stream": "0.1.1", "from": "0.1.7", "map-stream": "0.0.7", "pause-stream": "0.0.11", @@ -1117,7 +1245,6 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "optional": true, "requires": { "concat-stream": "1.6.2", "debug": "2.6.9", @@ -1132,7 +1259,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { @@ -1145,6 +1272,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fast-safe-stringify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" + }, "fd-slicer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", @@ -1153,6 +1285,11 @@ "pend": "1.2.0" } }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -1170,7 +1307,7 @@ "requires": { "is-number": "2.1.0", "isobject": "2.1.0", - "randomatic": "3.1.0", + "randomatic": "3.1.1", "repeat-element": "1.1.3", "repeat-string": "1.6.1" } @@ -1190,9 +1327,9 @@ "dev": true }, "flatmap-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.0.tgz", - "integrity": "sha512-Nlic4ZRYxikqnK5rj3YoxDVKGGtUjcNDUtvQ7XsdGLZmMwdUYnXf10o1zcXtzEZTBgc6GxeRpQxV/Wu3WPIIHA==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.1.tgz", + "integrity": "sha512-lAq4tLbm3sidmdCN8G3ExaxH7cUCtP5mgDvrYowsx84dcYkJJ4I28N7gkxA6+YlSXzaGLJYIDEi9WGfXzMiXdw==", "dev": true }, "for-in": { @@ -1214,23 +1351,13 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.20" - }, - "dependencies": { - "combined-stream": { - "version": "1.0.6", - "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "requires": { - "delayed-stream": "1.0.0" - } - } + "combined-stream": "1.0.7", + "mime-types": "2.1.21" } }, "formidable": { @@ -1256,7 +1383,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "optional": true, "requires": { "graceful-fs": "4.1.11", "jsonfile": "2.4.0", @@ -1333,6 +1459,22 @@ "file-uri-to-path": "1.0.0", "ftp": "0.3.10", "readable-stream": "2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "get-value": { @@ -1760,9 +1902,9 @@ } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-value": { @@ -1823,21 +1965,20 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "optional": true, "requires": { "is-stream": "1.1.0", "pinkie-promise": "2.0.1" } }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, "highlight.js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", - "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz", + "integrity": "sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==", "dev": true }, "hosted-git-info": { @@ -1846,14 +1987,14 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" }, "html-minifier": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.20.tgz", - "integrity": "sha512-ZmgNLaTp54+HFKkONyLFEfs5dd/ZOtlquKaTnqIWFmx3Av5zG6ZPcV2d0o9XM2fXOTxxIf6eDcwzFFotke/5zA==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", "requires": { "camel-case": "3.0.0", "clean-css": "4.2.1", "commander": "2.17.1", - "he": "1.1.1", + "he": "1.2.0", "param-case": "2.1.1", "relateurl": "0.2.7", "uglify-js": "3.4.9" @@ -1867,16 +2008,23 @@ } }, "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz", + "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==", "requires": { "domelementtype": "1.3.0", "domhandler": "2.4.2", "domutils": "1.5.1", - "entities": "1.1.1", + "entities": "1.1.2", "inherits": "2.0.3", - "readable-stream": "2.3.6" + "readable-stream": "3.0.6" + }, + "dependencies": { + "domelementtype": { + "version": "1.3.0", + "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + } } }, "http-errors": { @@ -1916,7 +2064,7 @@ "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", - "sshpk": "1.14.2" + "sshpk": "1.15.1" } }, "https-proxy-agent": { @@ -1925,13 +2073,13 @@ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "requires": { "agent-base": "4.2.1", - "debug": "3.2.5" + "debug": "3.2.6" }, "dependencies": { "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "requires": { "ms": "2.1.1" } @@ -2138,11 +2286,6 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" - }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -2184,12 +2327,12 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "js-beautify": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.8.6.tgz", - "integrity": "sha512-TYDZa+lg8vEC5U0OmGQEEwiZ0XFBfvZAUeNOtqflLe+woKuIqF4JzlsBx/C1KVYW5lUewZy2ODL4Obq6sH7a4Q==", + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.8.8.tgz", + "integrity": "sha512-qVNq7ZZ7ZbLdzorvSlRDadS0Rh5oyItaE95v6I4wbbuSiijxn7SnnsV6dvKlcXuO2jX7lK8tn9fBulx34K/Ejg==", "requires": { "config-chain": "1.1.12", - "editorconfig": "0.15.0", + "editorconfig": "0.15.2", "mkdirp": "0.5.1", "nopt": "4.0.1" } @@ -2199,11 +2342,28 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-bigint": { "version": "0.2.3", @@ -2241,7 +2401,6 @@ "version": "2.4.0", "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "optional": true, "requires": { "graceful-fs": "4.1.11" } @@ -2269,7 +2428,7 @@ "integrity": "sha512-3Qym/RnFoCGa9qrDz6xn4zRnohgI6G87xKWZV+/seF3dYpaVqNS1HijsDef+elGhytRY79RIboOzk0hucLtx6g==", "requires": { "cheerio": "0.22.0", - "commander": "2.18.0", + "commander": "2.19.0", "cross-spawn": "5.1.0", "deep-extend": "0.5.1", "mensch": "0.3.3", @@ -2292,8 +2451,7 @@ "kew": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", - "optional": true + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=" }, "kind-of": { "version": "3.2.2", @@ -2307,11 +2465,18 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "optional": true, "requires": { "graceful-fs": "4.1.11" } }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "requires": { + "colornames": "1.1.1" + } + }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -2319,6 +2484,23 @@ "dev": true, "requires": { "readable-stream": "2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "lcid": { @@ -2443,6 +2625,25 @@ "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=" }, + "logform": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", + "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", + "requires": { + "colors": "1.3.2", + "fast-safe-stringify": "2.0.6", + "fecha": "2.3.3", + "ms": "2.1.1", + "triple-beam": "1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2491,7 +2692,7 @@ "dev": true, "requires": { "argparse": "1.0.10", - "entities": "1.1.1", + "entities": "1.1.2", "linkify-it": "2.0.3", "mdurl": "1.0.1", "uc.micro": "1.0.5" @@ -2534,6 +2735,23 @@ "dev": true, "requires": { "readable-stream": "2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "methods": { @@ -2567,16 +2785,16 @@ "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==" }, "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" }, "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "requires": { - "mime-db": "1.36.0" + "mime-db": "1.37.0" } }, "mimer": { @@ -2622,346 +2840,367 @@ } }, "mjml": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml/-/mjml-4.1.2.tgz", - "integrity": "sha512-GgDa7fIG2JLsvvRX5DjtpkYOYfai+3f3b8LImjAhFHz8aRtaUR4VH6zWgzIozILeEfbZ1kBj2Gl6uBIbA/itqg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml/-/mjml-4.2.0.tgz", + "integrity": "sha512-+XvQWME94Ana3XKKAFXYnMP6lDtvxVGqaWrcZKEAJV+fMpb5eFX4urvpyMhC02mJEpQpKdE7UTFMnIdi9ilF9g==", "requires": { "cross-env": "5.2.0", - "mjml-accordion": "4.1.2", - "mjml-body": "4.1.2", - "mjml-button": "4.1.2", - "mjml-carousel": "4.1.2", - "mjml-cli": "4.1.2", - "mjml-column": "4.1.2", - "mjml-core": "4.1.2", - "mjml-divider": "4.1.2", - "mjml-group": "4.1.2", - "mjml-head": "4.1.2", - "mjml-head-attributes": "4.1.2", - "mjml-head-breakpoint": "4.1.2", - "mjml-head-font": "4.1.2", - "mjml-head-preview": "4.1.2", - "mjml-head-style": "4.1.2", - "mjml-head-title": "4.1.2", - "mjml-hero": "4.1.2", - "mjml-image": "4.1.2", - "mjml-migrate": "4.1.2", - "mjml-navbar": "4.1.2", - "mjml-raw": "4.1.2", - "mjml-section": "4.1.2", - "mjml-social": "4.1.2", - "mjml-spacer": "4.1.2", - "mjml-table": "4.1.2", - "mjml-text": "4.1.2", - "mjml-validator": "4.1.2", - "mjml-wrapper": "4.1.2" + "mjml-accordion": "4.2.0", + "mjml-body": "4.2.0", + "mjml-button": "4.2.0", + "mjml-carousel": "4.2.0", + "mjml-cli": "4.2.0", + "mjml-column": "4.2.0", + "mjml-core": "4.2.0", + "mjml-divider": "4.2.0", + "mjml-group": "4.2.0", + "mjml-head": "4.2.0", + "mjml-head-attributes": "4.2.0", + "mjml-head-breakpoint": "4.2.0", + "mjml-head-font": "4.2.0", + "mjml-head-preview": "4.2.0", + "mjml-head-style": "4.2.0", + "mjml-head-title": "4.2.0", + "mjml-hero": "4.2.0", + "mjml-image": "4.2.0", + "mjml-migrate": "4.2.0", + "mjml-navbar": "4.2.0", + "mjml-raw": "4.2.0", + "mjml-section": "4.2.0", + "mjml-social": "4.2.0", + "mjml-spacer": "4.2.0", + "mjml-table": "4.2.0", + "mjml-text": "4.2.0", + "mjml-validator": "4.2.0", + "mjml-wrapper": "4.2.0" } }, "mjml-accordion": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.1.2.tgz", - "integrity": "sha512-0KKqftPALfJVLS3e4+3GVYg6r0KuY+h3oHbQ/uzh4by8pQ9yPOeYfSukeLwFv/IwdAOJon6jfNe13CdCB+3UeA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.2.0.tgz", + "integrity": "sha512-Hl3a8yE8QYSSFIPqaeotuXupVJsN3uc/z+dd4CugqdFJPoTBV2V6FsBMIH5k1NYAzWNPZ32mnJZZXRH/yYqLRQ==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-body": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.1.2.tgz", - "integrity": "sha512-tfo39payfK1nMeUzdNoH76QponI52Aqsniq4skqIHSgpjtcGt9Q4PJCpaH/xIZmHJbH/lbootqgoNwCS1MmDyA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.2.0.tgz", + "integrity": "sha512-W33L/oxnLTsZ7zKJtnQ+Ob/OwDFcgsFhfVHLamjCNufe4eh06XLo6nJDFy+++oErXXXymD0M8OKJs1Pp6ycivg==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-button": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.1.2.tgz", - "integrity": "sha512-UvF08l3eWpL6nf4ywpFtLpu0N2QRMKfAampn/W1LPa3ezolDrLBfr5g86SDoCfyZiPJPv31FF9wDv9PwB32hHw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.2.0.tgz", + "integrity": "sha512-ekVYLwgVptfExdGgOJ7m+2F7apqQJ5VQTbKA7a4aEQ/fmzEGnXp1BzRmdqU2oZsXl+kzIpLUo/BhiRj/V7C+Zw==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-carousel": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.1.2.tgz", - "integrity": "sha512-/m5CGcWYLh0u6q/fafOCn6xiISBt3N5Y+wle14jxGTZCB8M3+6wW4jpaMJQLHxqd16FFV1T6mRCbrJvcg1XaJg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.2.0.tgz", + "integrity": "sha512-dYuDIYdGNezDJ5/W1GpgQXOx6dCffJEdWZoUP4eS37+TWON7Cs+5bFR4A98ZWciAHmrqBu0XVnyxudUMZcPJ+A==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-cli": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.1.2.tgz", - "integrity": "sha512-wlUBKW+CdKEHuGdMv3cbhBnvStESxyQJWJcyD0r/Ql6r9gueus5EdMwMqKxYJz+hQuxBtRUB7MPwYM6fW3tERQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.2.0.tgz", + "integrity": "sha512-QHQ6OQgBkZmLhg33UWYqOCIIis3gHZLTfjs8V4scEY0smRjUcUZLsvgsedQYU1Sje5xY6BcBVoQ2pk4SvTghAA==", "requires": { "babel-runtime": "6.26.0", "chokidar": "1.7.0", "cross-env": "5.2.0", "glob": "7.1.3", - "js-beautify": "1.8.6", + "js-beautify": "1.8.8", "lodash": "4.17.11", - "mjml-core": "4.1.2", - "mjml-migrate": "4.1.2", - "mjml-parser-xml": "4.1.2", - "mjml-validator": "4.1.2", + "mjml-core": "4.2.0", + "mjml-migrate": "4.2.0", + "mjml-parser-xml": "4.2.0", + "mjml-validator": "4.2.0", "yargs": "8.0.2" } }, "mjml-column": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.1.2.tgz", - "integrity": "sha512-KD++3EP9TNT78HHVPYOFnMak/tq0phzNTfqvEiDV5YWd2A7COao9AqroI4v9D5obOaSLhT/Tag6+YoK7iIrg+g==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.2.0.tgz", + "integrity": "sha512-cPtJrVcupYk+sph2hEbGAjrbbk/R56iG9sTQtIgP1Fpsp+ofC+jqy6IPU65KforJChrAVHbbInSiIim1ys4NBg==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-core": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.1.2.tgz", - "integrity": "sha512-AQLUeKxY6HT7jnC6CXxkSypiTll4d3Ya2R6yd1snWZJAIbBWf1ONMItIxxzXnvfJZKnuibmQBKCCwfpQG4UE2A==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.2.0.tgz", + "integrity": "sha512-QNEJkeOHLT3Q3SPtRw2M5ZIsdRyFJ2BpPrb3HxCXkcFADYMNqufOR8LeupwWV29VFQLzAU9+aOr8TUIBmEL9vw==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", - "html-minifier": "3.5.20", - "js-beautify": "1.8.6", + "html-minifier": "3.5.21", + "js-beautify": "1.8.8", "juice": "4.3.2", "lodash": "4.17.11", - "mjml-migrate": "4.1.2", - "mjml-parser-xml": "4.1.2", - "mjml-validator": "4.1.2" + "mjml-migrate": "4.2.0", + "mjml-parser-xml": "4.2.0", + "mjml-validator": "4.2.0" } }, "mjml-divider": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.1.2.tgz", - "integrity": "sha512-kxBMftHNfqzHZvq7ElISsPK4w2TMdZsAvfEFWdSNlwWfHByNpw7ojDivbOlMdKkZ3w21UYVI23CH6nczf16GCw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.2.0.tgz", + "integrity": "sha512-8fbDnSe8XyLkFgneLlBQybOAmszU5xqsiH/B8trafW52dCsEJrakb6lAJxRH143KWrM+EGvUkZ3VgU4c2Caxqw==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-group": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.1.2.tgz", - "integrity": "sha512-Oupu9CTECxyFPjf2JLuKWKZHVLUNst4Er3PHFf/fqaGvXsLUptg8WFIzQhZhwJ2Dp14D5ERg4m5tImzoC2D9OA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.2.0.tgz", + "integrity": "sha512-8iHbe2c3DVqLJtairTjjjkxZbCk/YeLFrkcqpPMok6uM20LS2jIRv7bmVsGbnx7M32GA+2GFyYg6dGOjgkYDzA==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-head": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.1.2.tgz", - "integrity": "sha512-SMv6LUXLESY1KqRz0HgWyr3hHAHdE+qDOxDo1YLJQFZRxLJTBE9j/OFVJRsb1kDGj2ijz63NuSsgT+gusj1Uig==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.2.0.tgz", + "integrity": "sha512-hUzKBxL3g3FbWOdpRaCErPOkRusNVSKKjvkd4E/H6mSY5FsB/wUaYabReSSTa8U2NgA+MWvosgN2ZdK3UVK6kw==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-head-attributes": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.1.2.tgz", - "integrity": "sha512-WnVlfXzboq+RK/aP8c9wVGbewMkoehT5G2TYXrWTNwn5bQmgWxVsTQ5/hSr11VO99DdOv2N+gvqkktxC8pv2qA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.2.0.tgz", + "integrity": "sha512-ktA4flJasjHFC+j5PHMg5a7z8Sqovx9CzwZ/GUVpgfwYtUqnNZVhe9pYLJKWzZvipF8s+gmoRqg7hSsApkNL1Q==", "requires": { "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-head-breakpoint": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.1.2.tgz", - "integrity": "sha512-PdR4L3mn8bSYg20vi5QP/Wv3VahltQJmzsvfohf3XQ7Sl+evsEgVMdSKSXpWUzatHG/j1o8Q8I9WhM8y5IWsGQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.2.0.tgz", + "integrity": "sha512-CI+bJ7z+r2NPQy+jclbd24E5NQeuHGH+BB1Ky39Tf9zVqVSw5BvlXBp/vRSlmsHVzom5gGiR9odBjT4q+bPJgQ==", "requires": { "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-head-font": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.1.2.tgz", - "integrity": "sha512-JH8DPkAiI5C3jOus/xAWHkY40JUJqghuU3CDLeyNvtvjSEgqtp9UshUNacPXmd1ghLhgbK2e6g8ZyDdtuJ29jQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.2.0.tgz", + "integrity": "sha512-19Ij8fpJMa2s5lKrfeKRwpMchZcbM58mLBSY2jhHRqt8rIR+cqvHLiOC3HgPeO9QABHIRWEuAMGrB24I5gurFQ==", "requires": { "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-head-preview": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.1.2.tgz", - "integrity": "sha512-IwHJm9rgRothRoi2BJ0Sa+LiYVrVoYutJnrNg7OHqousjAlqj2HRMQ8NBuI7WvUmV8z4TWrbznB5jfhiIIdDHw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.2.0.tgz", + "integrity": "sha512-ZksdIXPFVtpA0CH4pJMjNUCr4g6Z46AFa1qenl6jHj1lnrrmo2D6s4lLgXlgkp/49hnvkg9eczajzD+LYgAi2A==", "requires": { "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-head-style": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.1.2.tgz", - "integrity": "sha512-+bFcJ/PlrPbzlLkwJgXtFchFfhbqIxAYQVSauaYOFLaWpDJbr48zm/RGpij9sDZxHl6OvZawcex0FWHDxDb7Vw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.2.0.tgz", + "integrity": "sha512-VjgrWxf1qSix2vJx82xHVeYMkbdwZDIG8W1cPKTSMFcLozm873V1NtCnjM//FDXXRzqOYpyi5Hn6LeF+Sn76pw==", "requires": { "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-head-title": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.1.2.tgz", - "integrity": "sha512-wB2Lw9BbgoRBftYdzXbt9xqJi0xN7V3nxZ0+UG0TZsF7JxfWPyCN6RsPoNxK/bH47lwQ2DqWiMUEstZRmP9v3Q==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.2.0.tgz", + "integrity": "sha512-Pmtn7XGDs9C/UmWGOzUOnWpMT+AJBBkmsa2Rcw0rMDuXOIRGZuP2/IlFz2J5ZXNvczEFeShDtx6uuv7YbiirGA==", "requires": { "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-hero": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.1.2.tgz", - "integrity": "sha512-xWm0nz7wBUfsyhQVrj+9dL51RrCFS4Xj13Y3xH6EMl0QLDfBE2PXpA8cuBfHNwtGhkE7cO6rhww6HMmEHLrEMg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.2.0.tgz", + "integrity": "sha512-D56nFtYdJ89BPvn+SWeTwL4HBQBsk6RTvL2XV2Un6IUHj+QxxVF20IMT4jmC0zezNr1FrLY6pgA2ZclGKqczPw==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-image": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.1.2.tgz", - "integrity": "sha512-ocPeH553cyBgvViKz6raxRMZedhEmC67SQE+AVI7RGtZh35eJwZfnRm/8NhQiJBQLHnQC9+yxKIs46YtZYU2rg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.2.0.tgz", + "integrity": "sha512-CXp2B2Mw0B+AxkfkqZT0Olru2VJzxs3SLKvFAD0x61aD7DY0MoJ2kz+WemR/OHWr9Ez6VtVnthgT6M5lZ69Xig==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-migrate": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.1.2.tgz", - "integrity": "sha512-GiGXXm1hnbOAEqCdjM1ckhF8wSRyVoQiSIni4/K474lKjopBKg7wP5sg79gjKvcWSRJQn1MmWHq4YFG1aQFboQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.2.0.tgz", + "integrity": "sha512-KN1T1tPzj2YaprrBGbYcxyTVM3bDjnxPnSBjXMvJ0yKg7fCRRsXCLvKrm/yQ+BMsLo9GC0+DmS5Qih2CLR3Eaw==", "requires": { - "commander": "2.18.0", + "babel-runtime": "6.26.0", + "commander": "2.19.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2", - "mjml-parser-xml": "4.1.2" + "mjml-core": "4.2.0", + "mjml-parser-xml": "4.2.0" } }, "mjml-navbar": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.1.2.tgz", - "integrity": "sha512-oCpg9xiXJmtWyducIZNJNHqfnV6A/0glcL6Icw5llwmwu0/4+FA3gPQbqmBYDZ1oAT98ihN+5Y8NSt7NVWBWfg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.2.0.tgz", + "integrity": "sha512-uvrxcpzY6O/hQd7h6w4z97zVawoXJYch9t6qQmKmTnaosf00fPPbQEwjccjh68v14ttlAtsFH+H4yup5G9vFng==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-parser-xml": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.1.2.tgz", - "integrity": "sha512-rFbchrnHEFzaiuLXx/4x3heaDk047rhhgm7SVcjir3BxwXGd5QcclLhV8MOvZRXR2WMw/BJgf/pmBqZAm448zA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.2.0.tgz", + "integrity": "sha512-5aKcW/KjAwohB5jbo+FhY0Cu1uB4lt1FVRU41XQHC2uzLqeqhMTQyI0fWqqmBR9BelGBy1kt3ufTn1RLnVH2TQ==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", - "htmlparser2": "3.9.2", + "htmlparser2": "3.10.0", "lodash": "4.17.11" } }, "mjml-raw": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.1.2.tgz", - "integrity": "sha512-qXJq1hbCnFU/gOyk//WIuoGi6fAvAmfDbAoYuY1/AMEJ9mAKPw1CcTiHJDkxVWh2VXLqp9aEWEQavIvFx+wQyQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.2.0.tgz", + "integrity": "sha512-qw/scax1EVFmex6Rfp4UcIO/NnvG/WvMi18WlankSKcTW1YHkreHiQm74qVf+lTxGZWhPFyQ2BOcwKdZZuj3SA==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-section": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.1.2.tgz", - "integrity": "sha512-kFtt8loDYIlLJV0onXr2vvIDDGhOlfDSzoWkgPTJ2RXs2l0rLQydVHYL2Y/g0OqZNGQb8JSROwRpgk/iyAPXOQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.2.0.tgz", + "integrity": "sha512-uKxhVQA4Vha2X3H2LlFWB8LTjJmhNsyFE6tMimtnEbA/BiM/zpWJJXxWyTLX/WZs9ddDRmvJY7x76yUfF/X/Fg==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-social": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.1.2.tgz", - "integrity": "sha512-vhu7CdC6k+JFhtKJ90kN7tnCwcqA+0zyZuG+AQ6xzDGoOgUaIL0yDCzRILXjbI1S0e+QqY/BOdupodLhi7dotQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.2.0.tgz", + "integrity": "sha512-cz/g+PQfXrp3tWG5QwWeO8lReQbYPp7JeQkQ30TiUgS4pEayiAxufCYggq5vM5YCG6q0ZZbGaBUk+B5TNJJltA==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-spacer": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.1.2.tgz", - "integrity": "sha512-Ib9Di34WKkaoi3y8vVvj7u5/cOr9KBAW9r+JpurXy3wWkSVJM3W++c/PaBekPuQLLKXtDoDNTDyKxadn6DnlwA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.2.0.tgz", + "integrity": "sha512-wM7e/RTQ4rsNtFZWJ0r6S/GVLoR8FqcQathpk+mCI6Vk74u98rG+M7Mb0eUN9RP2HuDxEjXhRxBGDCZ2cjxqdA==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-table": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.1.2.tgz", - "integrity": "sha512-B63SZQSMSZIiae9mFggynMTZ72GC6VAFsJ92KaVqH635jp/NPXbAiro5rMMulhWgOfGEG+1/EW0AVKzLXA+zlQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.2.0.tgz", + "integrity": "sha512-fyVesmzCO+gFJmBSjdvgEm/ELiQ59hvtxX/BV7uYdj1T5VpkeROrW19wvUjnZAprVE+kGS0Ryq8RL6YE+e1LsA==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-text": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.1.2.tgz", - "integrity": "sha512-4WafRLrVbeOILiBSuil5cHdthiDZZhOBREY9fvFRJzr3XFYMAxuaMsqjoodpmDUMbGKZ7VSzdreV5ypNp2FbCA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.2.0.tgz", + "integrity": "sha512-svZZzkCTwtAgrpxBca2KV0+BVDE7eEKK4fVUMHqgTrcMXLt9Msn0USmtaosB6mPO9DTatanB94CaAotlKu16hg==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2" + "mjml-core": "4.2.0" } }, "mjml-validator": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.1.2.tgz", - "integrity": "sha512-i5vu3v+nHgd7m5fccQTTO2w4hHdBe5x1MQQUML0GJgO4W46x8DJ6sDjXrO7q3QITmp/18LqEd0tHQoXqATL7Ow==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.2.0.tgz", + "integrity": "sha512-5TI4DUM5Eb08wjflsT/aEiuyGs2mHKmT0zzlJQcRVNSAGK2dstmBxKgF5ndS4UgvawCypHsa75kOJpg+llNaFw==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2", "warning": "3.0.0" } }, "mjml-wrapper": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.1.2.tgz", - "integrity": "sha512-BzCCmm/EGGlisWHy3nb13giJ2GZtw5dqUQjuV0HYWIITdDlTbZbmjHDbsRjHPHfgkTkKQIXw4y+ULfZyM7/buw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.2.0.tgz", + "integrity": "sha512-6FUcUoxN3YoN55gf15CTxQzmW7hT65m5EQygSUPbdoKbNQpcEE0N4q9827Coyg8LNZ/ggPM5XPUFl3pmc2u49g==", "requires": { + "babel-runtime": "6.26.0", "cross-env": "5.2.0", "lodash": "4.17.11", - "mjml-core": "4.1.2", - "mjml-section": "4.1.2" + "mjml-core": "4.2.0", + "mjml-section": "4.2.0" } }, "mkdirp": { @@ -3005,6 +3244,12 @@ "ms": "2.0.0" } }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -3019,6 +3264,18 @@ "path-is-absolute": "1.0.1" } }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3106,9 +3363,9 @@ "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA==" }, "node-mailjet": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-3.3.0.tgz", - "integrity": "sha512-kOs4ajsNrB7IdNfqSCjk8pO3hNuL6je64Aa5eScIQMHe7Gk/4G6k0/+3ywMvgT7wQW1UaRCDW1AMTYp5l688tg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-3.3.1.tgz", + "integrity": "sha512-MMKE5e1vKv3/GMUa6GRZu4rloSNx3Aa/XlOzjr1P7jo9HFSDgzM1V7Tyi/p2/zPzt1nS5BT2vwiaV+YA8l0BcA==", "requires": { "bluebird": "3.5.2", "json-bigint": "0.2.3", @@ -3147,7 +3404,7 @@ "requires": { "hosted-git-info": "2.7.1", "is-builtin-module": "1.0.0", - "semver": "5.5.1", + "semver": "5.6.0", "validate-npm-package-license": "3.0.4" } }, @@ -5864,9 +6121,9 @@ } }, "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "requires": { "boolbase": "1.0.0" } @@ -5954,6 +6211,11 @@ "wrappy": "1.0.2" } }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -5975,6 +6237,23 @@ "requires": { "is-stream": "1.1.0", "readable-stream": "2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "os-homedir": { @@ -6038,7 +6317,7 @@ "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", "requires": { "agent-base": "4.2.1", - "debug": "3.2.5", + "debug": "3.2.6", "get-uri": "2.0.2", "http-proxy-agent": "2.1.0", "https-proxy-agent": "2.2.1", @@ -6048,9 +6327,9 @@ }, "dependencies": { "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "requires": { "ms": "2.1.1" } @@ -6127,6 +6406,12 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, + "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": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", @@ -6154,11 +6439,20 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "phantom": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/phantom/-/phantom-6.0.3.tgz", + "integrity": "sha512-8bb8urWoUiZ0E+JC4goaYBDPxljTnnxGwogz5cvash2SQovf//QAPoshXQz06kY/tpI+5caBVng0K0oZkVMNIQ==", + "requires": { + "phantomjs-prebuilt": "2.1.16", + "split": "1.0.1", + "winston": "3.1.0" + } + }, "phantomjs-prebuilt": { "version": "2.1.16", "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "optional": true, "requires": { "es6-promise": "4.2.5", "extract-zip": "1.6.7", @@ -6173,20 +6467,18 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "optional": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "optional": true, "requires": { "pinkie": "2.0.4" } @@ -6259,9 +6551,8 @@ }, "progress": { "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "optional": true + "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=" }, "proto-list": { "version": "1.2.4", @@ -6274,7 +6565,7 @@ "integrity": "sha512-CNKuhC1jVtm8KJYFTS2ZRO71VCBx3QSA92So/e6NrY6GoJonkx3Irnk4047EsCcswczwqAekRj3s8qLRGahSKg==", "requires": { "agent-base": "4.2.1", - "debug": "3.2.5", + "debug": "3.2.6", "http-proxy-agent": "2.1.0", "https-proxy-agent": "2.2.1", "lru-cache": "4.1.3", @@ -6284,9 +6575,9 @@ }, "dependencies": { "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "requires": { "ms": "2.1.1" } @@ -6324,9 +6615,9 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", "dev": true }, "queue": { @@ -6339,9 +6630,9 @@ } }, "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "requires": { "is-number": "4.0.0", "kind-of": "6.0.2", @@ -6401,15 +6692,11 @@ } }, "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.0.6.tgz", + "integrity": "sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg==", "requires": { - "core-util-is": "1.0.2", "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } @@ -6671,6 +6958,20 @@ "snapdragon": "0.8.2", "to-regex": "3.0.2" } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } } } }, @@ -6733,13 +7034,13 @@ "combined-stream": "1.0.7", "extend": "3.0.2", "forever-agent": "0.6.1", - "form-data": "2.3.2", + "form-data": "2.3.3", "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.20", + "mime-types": "2.1.21", "oauth-sign": "0.9.0", "performance-now": "2.1.0", "qs": "6.5.2", @@ -6753,7 +7054,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "optional": true, "requires": { "throttleit": "1.0.0" } @@ -6774,6 +7074,15 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "1.0.6" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -6800,7 +7109,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { "ret": "0.1.15" @@ -6812,9 +7121,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, "set-blocking": { "version": "2.0.0", @@ -6870,6 +7179,21 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "0.3.2" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, "slick": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz", @@ -7033,9 +7357,9 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "spdx-correct": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.1.tgz", - "integrity": "sha512-hxSPZbRZvSDuOvADntOElzJpenIR7wXJkuoUcUtS0erbgt2fgeaoPIYretfKpslMhfFDY4k0MZ2F5CUzhBsSvQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", "requires": { "spdx-expression-parse": "3.0.0", "spdx-license-ids": "3.0.1" @@ -7064,7 +7388,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, "requires": { "through": "2.3.8" } @@ -7084,9 +7407,9 @@ "dev": true }, "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", "requires": { "asn1": "0.2.4", "assert-plus": "1.0.0", @@ -7099,6 +7422,11 @@ "tweetnacl": "0.14.5" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "stat-mode": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", @@ -7152,6 +7480,23 @@ "dev": true, "requires": { "readable-stream": "2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "streamifier": { @@ -7233,7 +7578,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "superagent": { @@ -7243,9 +7588,9 @@ "requires": { "component-emitter": "1.2.1", "cookiejar": "2.1.2", - "debug": "3.2.5", + "debug": "3.2.6", "extend": "3.0.2", - "form-data": "2.3.2", + "form-data": "2.3.3", "formidable": "1.2.1", "methods": "1.1.2", "mime": "1.6.0", @@ -7254,9 +7599,9 @@ }, "dependencies": { "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "requires": { "ms": "2.1.1" } @@ -7270,6 +7615,20 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } } } }, @@ -7278,14 +7637,14 @@ "resolved": "http://registry.npmjs.org/superagent-proxy/-/superagent-proxy-1.0.3.tgz", "integrity": "sha512-79Ujg1lRL2ICfuHUdX+H2MjIw73kB7bXsIkxLwHURz3j0XUmEEEoJ+u/wq+mKwna21Uejsm2cGR3OESA00TIjA==", "requires": { - "debug": "3.2.5", + "debug": "3.2.6", "proxy-agent": "2.3.1" }, "dependencies": { "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "requires": { "ms": "2.1.1" } @@ -7319,17 +7678,20 @@ "inherits": "2.0.3" } }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "optional": true + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=" }, "through": { "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.3", @@ -7339,6 +7701,23 @@ "requires": { "readable-stream": "2.3.6", "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } } }, "through2-filter": { @@ -7356,14 +7735,6 @@ "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "1.0.2" - } - }, "to-absolute-glob": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", @@ -7431,6 +7802,77 @@ "punycode": "1.4.1" } }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, + "tslint": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", + "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "builtin-modules": "1.1.1", + "chalk": "2.4.1", + "commander": "2.19.0", + "diff": "3.5.0", + "glob": "7.1.3", + "js-yaml": "3.12.0", + "minimatch": "3.0.4", + "resolve": "1.8.1", + "semver": "5.6.0", + "tslib": "1.9.3", + "tsutils": "2.29.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "1.9.3" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" + } + }, + "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" + } + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "1.9.3" + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -7442,8 +7884,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { "version": "0.3.2", @@ -7456,13 +7897,12 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "optional": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typescript": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.1.tgz", - "integrity": "sha512-Veu0w4dTc/9wlWNf2jeRInNodKlcdLgemvPsrNpfu5Pq39sgfFjvIIgTsvUHCoLBnMhPoUA+tFxsXjU6VexVRQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.3.tgz", + "integrity": "sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA==", "dev": true }, "uc.micro": { @@ -7591,7 +8031,7 @@ "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", "dev": true, "requires": { - "querystringify": "2.0.0", + "querystringify": "2.1.0", "requires-port": "1.0.0" } }, @@ -7626,7 +8066,7 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "requires": { - "spdx-correct": "3.0.1", + "spdx-correct": "3.0.2", "spdx-expression-parse": "3.0.0" } }, @@ -7656,7 +8096,7 @@ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", "dev": true, "requires": { - "duplexify": "3.6.0", + "duplexify": "3.6.1", "glob-stream": "5.3.5", "graceful-fs": "4.1.11", "gulp-sourcemaps": "1.6.0", @@ -7681,6 +8121,21 @@ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", @@ -7735,7 +8190,7 @@ "gulp-vinyl-zip": "2.1.0", "mocha": "4.1.0", "request": "2.88.0", - "semver": "5.5.1", + "semver": "5.6.0", "source-map-support": "0.5.9", "url-parse": "1.4.3", "vinyl-source-stream": "1.1.2" @@ -7757,7 +8212,7 @@ "async": "2.6.1", "chalk": "1.1.3", "datauri": "1.1.0", - "htmlparser2": "3.9.2", + "htmlparser2": "3.10.0", "lodash.unescape": "4.0.1", "request": "2.88.0", "valid-data-url": "0.1.6", @@ -7777,6 +8232,63 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "winston": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", + "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==", + "requires": { + "async": "2.6.1", + "diagnostics": "1.1.1", + "is-stream": "1.1.0", + "logform": "1.10.0", + "one-time": "0.0.4", + "readable-stream": "2.3.6", + "stack-trace": "0.0.10", + "triple-beam": "1.3.0", + "winston-transport": "4.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } + } + }, + "winston-transport": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.2.0.tgz", + "integrity": "sha512-0R1bvFqxSlK/ZKTH86nymOuKv/cT1PQBMuDdA7k7f0S9fM44dNH6bXnuxwXPrN8lefJgtZq08BKdyZ0DZIy/rg==", + "requires": { + "readable-stream": "2.3.6", + "triple-beam": "1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/package.json b/package.json index 9f3f9cb..33e9924 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-mjml", "displayName": "MJML", "description": "MJML preview, lint, compile for Visual Studio Code.", - "version": "1.5.1", + "version": "1.6.0", "publisher": "attilabuti", "license": "MIT", "readme": "README.md", @@ -50,9 +50,10 @@ "onCommand:mjml.multipleScreenshots", "onCommand:mjml.previewToSide", "onCommand:mjml.screenshot", + "onCommand:mjml.searchInDocumentation", "onCommand:mjml.sendEmail", "onCommand:mjml.template", - "onCommand:mjml.searchInDocumentation", + "onCommand:mjml.version", "onLanguage:mjml" ], "main": "./out/extension", @@ -186,6 +187,16 @@ "default": false, "description": "Show the save as dialog instead of input box.", "type": "boolean" + }, + "mjml.templateGallery": { + "default": false, + "description": "Show the template gallery instead of quick pick.", + "type": "boolean" + }, + "mjml.templateGalleryAutoClose": { + "default": true, + "description": "Automatically close template gallery when selecting a template.", + "type": "boolean" } } }, @@ -195,8 +206,8 @@ "title": "Open Preview to the Side", "category": "MJML", "icon": { - "light": "./media/preview_icon_light.svg", - "dark": "./media/preview_icon_dark.svg" + "light": "./resources/icons/preview_icon_light.svg", + "dark": "./resources/icons/preview_icon_dark.svg" } }, { @@ -248,6 +259,11 @@ "command": "mjml.searchInDocumentation", "title": "Search in MJML documentation", "category": "MJML" + }, + { + "command": "mjml.version", + "title": "Version", + "category": "MJML" } ], "languages": [ @@ -300,29 +316,30 @@ "tslint": "tslint -c tslint.json src/extension.ts" }, "devDependencies": { - "@types/copy-paste": "1.1.30", - "@types/file-url": "2.0.0", - "@types/is-url": "^1.2.28", + "@types/copy-paste": "^1.1.30", + "@types/file-url": "^2.0.0", + "@types/js-beautify": "^1.8.0", "@types/mime": "^2.0.0", + "@types/node-fetch": "^2.1.2", "@types/node": "*", "@types/nodemailer": "^4.6.5", - "typescript": "^3.1.1", - "vscode": "^1.1.18", "@types/npm": "^2.0.29", - "markdown-it": "^8.4.2", + "highlight.js": "^9.13.1", "markdown-it-anchor": "^5.0.2", - "highlight.js": "^9.12.0" + "markdown-it": "^8.4.2", + "tslint": "^5.11.0", + "typescript": "^3.1.3", + "vscode": "^1.1.21" }, "dependencies": { - "ab-webshot": "^1.0.0", "copy-paste": "^1.3.0", - "is-url": "^1.2.4", - "js-beautify": "^1.8.6", + "js-beautify": "^1.8.8", "mime": "^2.3.1", - "mjml": "^4.1.2", - "node-fetch": "2.2.0", - "node-mailjet": "^3.3.0", + "mjml": "^4.2.0", + "node-fetch": "^2.2.0", + "node-mailjet": "^3.3.1", "nodemailer": "^4.6.8", - "npm": "^6.4.1" + "npm": "^6.4.1", + "phantom": "^6.0.3" } } diff --git a/media/preview_icon_dark.svg b/resources/icons/preview_icon_dark.svg similarity index 100% rename from media/preview_icon_dark.svg rename to resources/icons/preview_icon_dark.svg diff --git a/media/preview_icon_light.svg b/resources/icons/preview_icon_light.svg similarity index 100% rename from media/preview_icon_light.svg rename to resources/icons/preview_icon_light.svg diff --git a/resources/templates/gallery.html b/resources/templates/gallery.html new file mode 100644 index 0000000..97553be --- /dev/null +++ b/resources/templates/gallery.html @@ -0,0 +1,69 @@ + + + + + + + MJML Templates + + + + +
+ {{templates}} +
+ + \ No newline at end of file diff --git a/src/beautify.ts b/src/beautify.ts index 9ab8753..fdcb52c 100644 --- a/src/beautify.ts +++ b/src/beautify.ts @@ -1,50 +1,54 @@ -"use strict"; +import { commands, Disposable, languages, Position, Range, TextDocument, TextEdit, TextEditor, TextEditorEdit, window } from "vscode"; -import * as vscode from "vscode"; - -import helper from "./helper"; +import { beautifyHTML, isMJMLFile } from "./helper"; export default class Beautify { - constructor(subscriptions: vscode.Disposable[]) { + constructor(subscriptions: Disposable[]) { subscriptions.push( - vscode.commands.registerCommand("mjml.beautify", () => { + languages.registerDocumentFormattingEditProvider({ + language: "mjml", + scheme: "file" + }, { + provideDocumentFormattingEdits(document: TextDocument): TextEdit[] { + const formattedDocument: string | undefined = beautifyHTML(document.getText()); + if (formattedDocument) { + return [ TextEdit.replace(getRange(document), formattedDocument) ]; + } + + return [ TextEdit.replace(getRange(document), document.getText()) ]; + } + }), + + commands.registerCommand("mjml.beautify", () => { this.beautify(); }) ); } private beautify(): void { - if (helper.isMJMLFile(vscode.window.activeTextEditor.document)) { - vscode.window.activeTextEditor.edit((editBuilder: vscode.TextEditorEdit) => { - editBuilder.replace( - this.getRange(), - helper.beautifyHTML(vscode.window.activeTextEditor.document.getText()) - ); + const activeTextEditor: TextEditor | undefined = window.activeTextEditor; + + if (activeTextEditor && isMJMLFile(activeTextEditor.document)) { + activeTextEditor.edit((editBuilder: TextEditorEdit) => { + const formattedDocument: string | undefined = beautifyHTML(activeTextEditor.document.getText()); + + if (formattedDocument) { + editBuilder.replace(getRange(activeTextEditor.document), formattedDocument); + } }); - } - else { - vscode.window.showWarningMessage("This is not a MJML document!"); + } else { + window.showWarningMessage("This is not a MJML document!"); + return; } } - private getRange(): vscode.Range { - let document: vscode.TextDocument = vscode.window.activeTextEditor.document; - - return new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position(document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length) - ); - } - - public formatDocument(): vscode.TextEdit[] { - return [ - vscode.TextEdit.replace( - this.getRange(), - helper.beautifyHTML(vscode.window.activeTextEditor.document.getText()) - ) - ]; - } +} +function getRange(document: TextDocument): Range { + return new Range( + new Position(0, 0), + new Position(document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length) + ); } diff --git a/src/copy.ts b/src/copy.ts index 28252aa..3d4dd08 100644 --- a/src/copy.ts +++ b/src/copy.ts @@ -1,25 +1,23 @@ -"use strict"; +import { commands, Disposable, window } from "vscode"; -import * as vscode from "vscode"; +import { copy } from "copy-paste"; -import * as copyPaste from "copy-paste"; +import { renderMJML } from "./helper"; -import helper from "./helper"; +export default class Copy { -export default class CopyHTML { - - constructor(subscriptions: vscode.Disposable[]) { + constructor(subscriptions: Disposable[]) { subscriptions.push( - vscode.commands.registerCommand("mjml.copyHTML", () => { + commands.registerCommand("mjml.copyHTML", () => { this.copy(); }) ); } private copy(): void { - helper.renderMJML((content: string) => { - copyPaste.copy(content, () => { - vscode.window.showInformationMessage("Copied!"); + renderMJML((content: string) => { + copy(content, () => { + window.showInformationMessage("Copied!"); }); }); } diff --git a/src/documentation.ts b/src/documentation.ts index 1ac9892..e73ff9e 100644 --- a/src/documentation.ts +++ b/src/documentation.ts @@ -1,111 +1,129 @@ -"use strict"; - -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; - -export interface WebviewMessage { - command: string; - data: string; -} +import { existsSync, readFileSync, statSync } from "fs"; +import { join as joinPath } from "path"; +import { commands, ExtensionContext, TextDocument, TextEditor, Uri, ViewColumn, WebviewPanel, window, workspace } from "vscode"; export default class Documentation { - protected context: vscode.ExtensionContext; - protected webview: vscode.WebviewPanel | undefined; - protected content: string; + private content: string = ""; + private context: ExtensionContext; + private webview: WebviewPanel | undefined; + private webviewViewColumn: ViewColumn | undefined; - constructor(context: vscode.ExtensionContext) { + constructor(context: ExtensionContext) { this.context = context; - let documentationPath: string = path.join(__dirname, "../documentation/documentation.html"); + this.webviewViewColumn = ViewColumn.Two; context.subscriptions.push( - vscode.commands.registerCommand("mjml.documentation", () => { - if (documentationPath && fs.existsSync(documentationPath) && fs.statSync(documentationPath).isFile()) { - this.displayWebView(this.getWebviewContent(documentationPath)); - this.handleEvents(); - } + commands.registerCommand("mjml.documentation", () => { + this.displayWebView(); }), - vscode.commands.registerCommand("mjml.searchInDocumentation", () => { - let text: string = vscode.window.activeTextEditor.document.getText(vscode.window.activeTextEditor.selection); - let anchor: string = text.replace(/((\/|\<|\>)|^\s+|(\r?\n|\r)|\s.*)/gi, "").replace("mj-", "#mjml-"); - if (!anchor.startsWith("#mjml-")) { - anchor = `#mjml-${anchor}`; - } - - this.displayWebView(this.getWebviewContent(documentationPath)); - this.webview.webview.postMessage({ - command: "scrollTo", - anchor: anchor - }); - - this.handleEvents(); + commands.registerCommand("mjml.searchInDocumentation", () => { + this.searchInDocumentation(); }) ); } - private handleEvents(): void { - // Handle messages from the webview - this.webview.webview.onDidReceiveMessage((message: WebviewMessage) => { - if (message.command == "openExample") { - this.openExample(message.data); - } - }, undefined, this.context.subscriptions); - } - - private async openExample(fileName: string): Promise { - let file: string = path.join(__dirname, "../documentation/examples/", `${fileName}.mjml`); - - if (file && fs.existsSync(file) && fs.statSync(file).isFile()) { - let document: vscode.TextDocument = await vscode.workspace.openTextDocument({ - content: fs.readFileSync(file, "utf8"), - language: "mjml" - }); - - await vscode.window.showTextDocument(document, { - viewColumn: vscode.ViewColumn.One - }); - - await vscode.commands.executeCommand("mjml.previewToSide"); + public dispose(): void { + if (this.webview !== undefined) { + this.webview.dispose(); + this.webviewViewColumn = ViewColumn.Two; } } - private displayWebView(content: string): void { + private displayWebView(): void { if (!this.webview) { - this.webview = vscode.window.createWebviewPanel("mjml-documentation", "MJML Documentation", vscode.ViewColumn.Two, { - retainContextWhenHidden: true, + const documentationPath: string = joinPath(__dirname, "../documentation/documentation.html"); + if (!documentationPath || !existsSync(documentationPath) || !statSync(documentationPath).isFile()) { + return; + } + + this.webview = window.createWebviewPanel("mjml-documentation", "MJML Documentation", ViewColumn.Two, { enableFindWidget: true, enableScripts: true, localResourceRoots: [ - vscode.Uri.parse(this.context.extensionPath) - ] + Uri.parse(this.context.extensionPath) + ], + retainContextWhenHidden: true }); - this.webview.webview.html = content; + this.webview.webview.html = this.getWebviewContent(documentationPath); + + this.webview.onDidChangeViewState(() => { + if (this.webview && this.webviewViewColumn !== this.webview.viewColumn) { + this.webviewViewColumn = this.webview.viewColumn; + } + }); this.webview.onDidDispose(() => { this.webview = undefined; + this.webviewViewColumn = ViewColumn.Two; }); } + + this.webview.reveal(this.webviewViewColumn); + + this.handleEvents(); } private getWebviewContent(filePath: string): string { if (!this.content) { - let rootPath: string = vscode.Uri.parse(path.join(this.context.extensionPath, "documentation")).with({ scheme: "vscode-resource" }).toString(); - this.content = fs.readFileSync(filePath).toString().replace(/{{root}}/gi, rootPath); + const rootPath: string = Uri.parse(joinPath(this.context.extensionPath, "documentation")).with({ + scheme: "vscode-resource" + }).toString(); + + this.content = readFileSync(filePath).toString().replace(/{{root}}/gi, rootPath); } return this.content; } - public dispose(): void { - if (this.webview !== undefined) { - this.webview.dispose(); + private handleEvents(): void { + if (this.webview) { + // Handle messages from the webview + this.webview.webview.onDidReceiveMessage((message: WebviewMessage) => { + if (message.command === "openExample") { + this.openExample(message.data); + } + }, undefined, this.context.subscriptions); + } + } + + private searchInDocumentation(): void { + const activeTextEditor: TextEditor | undefined = window.activeTextEditor; + if (!activeTextEditor) { + return; } - for (let s of this.context.subscriptions) { - s.dispose(); + const text: string = activeTextEditor.document.getText(activeTextEditor.selection); + let anchor: string = text.replace(/((\/|\<|\>)|^\s+|(\r?\n|\r)|\s.*)/gi, "").replace("mj-", "#mjml-"); + if (!anchor.startsWith("#mjml-")) { + anchor = `#mjml-${anchor}`; + } + + this.displayWebView(); + if (this.webview) { + this.webview.webview.postMessage({ + anchor, + command: "scrollTo" + }); + } + } + + private async openExample(fileName: string): Promise { + const filePath: string = joinPath(__dirname, "../documentation/examples/", `${fileName}.mjml`); + + if (filePath && existsSync(filePath) && statSync(filePath).isFile()) { + const document: TextDocument = await workspace.openTextDocument({ + content: readFileSync(filePath, "utf8"), + language: "mjml" + }); + + await window.showTextDocument(document, { + viewColumn: ViewColumn.One + }); + + await commands.executeCommand("mjml.previewToSide"); } } diff --git a/src/email.ts b/src/email.ts index 553624e..666e39e 100644 --- a/src/email.ts +++ b/src/email.ts @@ -1,148 +1,157 @@ -"use strict"; +import { createReadStream, existsSync, readFileSync, statSync } from "fs"; +import { basename, dirname, join as joinPath } from "path"; +import { commands, Disposable, ProgressLocation, window, workspace } from "vscode"; -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; +import { getType as getMimeType } from "mime"; +import { connect as mailjetConnect } from "node-mailjet"; +import { createTransport, getTestMessageUrl } from "nodemailer"; -import * as mailjet from "node-mailjet"; -import * as nodemailer from "nodemailer"; -import * as mime from "mime"; -import isUrl = require("is-url"); +import { getPath, renderMJML } from "./helper"; -import helper from "./helper"; +export default class Email { -export default class SendEmail { - - constructor(subscriptions: vscode.Disposable[]) { + constructor(subscriptions: Disposable[]) { subscriptions.push( - vscode.commands.registerCommand("mjml.sendEmail", () => { - helper.renderMJML((content: string) => { - this.sendEmail(content, vscode.window.activeTextEditor.document.uri.fsPath); + commands.registerCommand("mjml.sendEmail", () => { + renderMJML((content: string) => { + this.sendEmail(content, getPath()); }); }) ); } private sendEmail(content: string, mjmlPath: string): void { - let mailer: string = vscode.workspace.getConfiguration("mjml").mailer.toLowerCase(); - - let defaultSubject: string = vscode.workspace.getConfiguration("mjml").mailSubject; - let defaultRecipients: string = vscode.workspace.getConfiguration("mjml").mailRecipients; + const mailer: string = workspace.getConfiguration("mjml").mailer.toLowerCase(); + const defaultRecipients: string = workspace.getConfiguration("mjml").mailRecipients; - vscode.window.showInputBox({ - prompt: "Subject", + window.showInputBox({ placeHolder: "Type a subject for the email.", - value: defaultSubject - }).then((subject: string) => { + prompt: "Subject", + value: workspace.getConfiguration("mjml").mailSubject + }).then((subject: string | undefined) => { if (!subject) { return; } - vscode.window.showInputBox({ - prompt: "Recipients", + window.showInputBox({ placeHolder: "Comma-separated list of recipients.", + prompt: "Recipients", value: defaultRecipients - }).then((recipients: string) => { + }).then(async (recipients: string | undefined) => { if (!recipients) { return; } - recipients = (recipients ? recipients : defaultRecipients).replace(/\s/g, ""); + await window.withProgress({ + cancellable: false, + location: ProgressLocation.Notification, + title: `Sending email...` + }, async () => { + recipients = (recipients ? recipients : defaultRecipients).replace(/\s/g, ""); - let attachments: any[] = this.createAttachments(content, mjmlPath, mailer); - content = this.replaceImages(content, attachments, mailer); + const attachments: Attachments[] = this.createAttachments(content, mjmlPath, mailer); + content = this.replaceImages(content, attachments, mailer); - if (mailer == "nodemailer") { - this.sendEmailWithNodemailer(subject, recipients, content, attachments); - } - else { - this.sendEmailWithMailjet(subject, recipients, content, attachments); - } + if (mailer === "nodemailer") { + await this.nodemailer(subject, recipients, content, attachments); + } else { + await this.mailjet(subject, recipients, content, attachments); + } + }); }); }); } - private sendEmailWithNodemailer(subject: string, recipients: string, content: string, attachments: any[]): void { - let transportOptions: any = vscode.workspace.getConfiguration("mjml").nodemailer; - - nodemailer.createTransport(transportOptions).sendMail({ - from: vscode.workspace.getConfiguration("mjml").mailFromName + " <" + vscode.workspace.getConfiguration("mjml").mailSender + ">", - to: recipients, - subject: subject, - html: content, - attachments: attachments - }, (err: Error, info: any) => { - if (err) { - vscode.window.showErrorMessage(err.message); - return; - } - - vscode.window.showInformationMessage("Mail has been sent successfully."); - - if (transportOptions.host && transportOptions.host == "smtp.ethereal.email") { - let url: (string | boolean) = nodemailer.getTestMessageUrl(info); + private async nodemailer( + subject: string, recipients: string, html: string, attachments: Attachments[] + ): Promise { + const transportOptions: any = workspace.getConfiguration("mjml").nodemailer; + + await createTransport(transportOptions).sendMail({ + attachments, + from: { + address: workspace.getConfiguration("mjml").mailSender, + name: workspace.getConfiguration("mjml").mailFromName + }, + html, + subject, + to: recipients + }).then((info: any) => { + window.showInformationMessage("Mail has been sent successfully."); + + if (transportOptions.host && transportOptions.host === "smtp.ethereal.email") { + const url: string | boolean = getTestMessageUrl(info); if (url) { - vscode.window.showInformationMessage(`Preview URL: ${url}`); + window.showInformationMessage(`Preview URL: ${url}`); } } + }).catch((error: Error | null) => { + if (error) { + window.showErrorMessage(error.message); + + return; + } }); } - private sendEmailWithMailjet(subject: string, recipients: string, content: string, attachments: any[]): void { - let recipientList: Array<{ Email: string }> = recipients.split(",").map((emailAddress: string) => { + private async mailjet( + subject: string, recipients: string, html: string, attachments: Attachments[] + ): Promise { + const recipientList: Array<{ Email: string }> = recipients.split(",").map((emailAddress: string) => { return { Email: emailAddress }; }); - mailjet.connect( - vscode.workspace.getConfiguration("mjml").mailjetAPIKey, - vscode.workspace.getConfiguration("mjml").mailjetAPISecret + await mailjetConnect( + workspace.getConfiguration("mjml").mailjetAPIKey, + workspace.getConfiguration("mjml").mailjetAPISecret ).post("send").request({ - FromEmail: vscode.workspace.getConfiguration("mjml").mailSender, - FromName: vscode.workspace.getConfiguration("mjml").mailFromName, - Subject: subject, - Recipients: recipientList, - "Html-part": content, - Inline_attachments: attachments - }).then((result: object) => { - vscode.window.showInformationMessage("Mail has been sent successfully."); - }).catch((err: any) => { - vscode.window.showErrorMessage(err.message); + "FromEmail": workspace.getConfiguration("mjml").mailSender, + "FromName": workspace.getConfiguration("mjml").mailFromName, + "Html-part": html, + "Inline_attachments": attachments, + "Recipients": recipientList, + "Subject": subject + }).then(() => { + window.showInformationMessage("Mail has been sent successfully."); + }).catch((error: any) => { + window.showErrorMessage(error.message); }); } - private createAttachments(content: string, mjmlPath: string, mailer?: string): any[] { - let imgPaths: string[] = []; + private createAttachments(content: string, mjmlPath: string, mailer?: string): Attachments[] { + const imgPaths: string[] = []; - let match: RegExpExecArray; - let pattern: RegExp = /]*?src=("|')([^"']+)\1/g; + let match: RegExpExecArray | null; + const pattern: RegExp = /]*?src=("|')([^"']+)\1/g; while (match = pattern.exec(content)) { imgPaths.push(match[2]); } - let attachments: any[] = []; - if (imgPaths) { - for (let i = 0; i < imgPaths.length; i++) { - if (imgPaths[i] && !isUrl(imgPaths[i])) { - let filePath: string = path.join(path.dirname(mjmlPath), imgPaths[i]); - - if (filePath && fs.existsSync(filePath) && fs.statSync(filePath).isFile()) { - if (mailer == "nodemailer") { - attachments.push({ - originalPath: imgPaths[i], - filename: path.basename(filePath), - content: fs.createReadStream(filePath), - cid: Math.random().toString(36).substring(2) + i - }); - } - else { - attachments.push({ - originalPath: imgPaths[i], - "Content-type": mime.getType(filePath), - Filename: i + "_" + path.basename(filePath), - content: fs.readFileSync(filePath).toString("base64") - }); - } + const attachments: Attachments[] = []; + if (!imgPaths) { + return attachments; + } + + for (let i = 0; i < imgPaths.length; i++) { + if (imgPaths[i] && !isURL(imgPaths[i])) { + const filePath: string = joinPath(dirname(mjmlPath), imgPaths[i]); + + if (filePath && existsSync(filePath) && statSync(filePath).isFile()) { + if (mailer === "nodemailer") { + attachments.push({ + cid: Math.random().toString(36).substring(2) + i, + content: createReadStream(filePath), + filename: basename(filePath), + originalPath: imgPaths[i] + }); + } else { + attachments.push({ + "Content-type": getMimeType(filePath), + "Filename": i + "_" + basename(filePath), + "content": readFileSync(filePath).toString("base64"), + "originalPath": imgPaths[i] + }); } } } @@ -151,12 +160,12 @@ export default class SendEmail { return attachments; } - private replaceImages(content: string, attachments: any[], mailer?: string): string { + private replaceImages(content: string, attachments: Attachments[], mailer?: string): string { if (attachments) { - for (let i = 0; i < attachments.length; i++) { + for (const attachment of attachments) { content = content.replace( - "src=\"" + attachments[i].originalPath + "\"", - "src=\"cid:" + ((mailer == "nodemailer") ? attachments[i].cid : attachments[i].Filename) + "\"" + `src="${attachment.originalPath}"`, + `src="cid:${((mailer === "nodemailer") ? attachment.cid : attachment.Filename)}"` ); } } @@ -165,3 +174,37 @@ export default class SendEmail { } } + +/** + * Regular Expression for URL validation + * Author: Diego Perini + * License: MIT + * https://gist.github.com/dperini/729294 + */ +function isURL(url: string): boolean { + return new RegExp( + "^" + + "(?:(?:(?:https?|ftp):)?\\/\\/)" + + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + + "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + "(?:" + + "(?:" + + "[a-z0-9\\u00a1-\\uffff]" + + "[a-z0-9\\u00a1-\\uffff_-]{0,62}" + + ")?" + + "[a-z0-9\\u00a1-\\uffff]\\." + + ")+" + + "(?:[a-z\\u00a1-\\uffff]{2,}\\.?)" + + ")" + + "(?::\\d{2,5})?" + + "(?:[/?#]\\S*)?" + + "$", "i" + ).test(url); +} diff --git a/src/export.ts b/src/export.ts index e7ea043..8cf7059 100644 --- a/src/export.ts +++ b/src/export.ts @@ -1,78 +1,70 @@ -"use strict"; +import { writeFile } from "fs"; +import { basename, resolve as resolvePath } from "path"; +import { commands, Disposable, Uri, window, workspace } from "vscode"; -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; +import { getPath, renderMJML } from "./helper"; -import helper from "./helper"; +export default class Export { -export default class ExportHTML { - - constructor(subscriptions: vscode.Disposable[]) { + constructor(subscriptions: Disposable[]) { subscriptions.push( - vscode.commands.registerCommand("mjml.exportHTML", () => { + commands.registerCommand("mjml.exportHTML", () => { this.export(); }) ); } private export(): void { - helper.renderMJML((content: string) => { - let defaultFileName: string = path.basename(vscode.window.activeTextEditor.document.uri.fsPath).replace(/\.[^\.]+$/, ""); + renderMJML((content: string) => { + const defaultFileName: string = basename(getPath()).replace(/\.[^\.]+$/, ""); - let exportType: string = vscode.workspace.getConfiguration("mjml").exportType; + let exportType: string = workspace.getConfiguration("mjml").exportType; if (!exportType.startsWith(".")) { - exportType = "." + exportType; + exportType = `.${exportType}`; } - if (vscode.workspace.getConfiguration("mjml").showSaveDialog) { - vscode.window.showSaveDialog({ - defaultUri: vscode.Uri.file(path.resolve(vscode.window.activeTextEditor.document.uri.fsPath, `../${defaultFileName}${exportType}`)), + if (workspace.getConfiguration("mjml").showSaveDialog) { + window.showSaveDialog({ + defaultUri: Uri.file(resolvePath(getPath(), `../${defaultFileName}${exportType}`)), filters: { - "HTML": ["html"], - "All files": ["*"] + "All files": ["*"], + "HTML": ["html"] } - }).then((fileUri: vscode.Uri) => { + }).then((fileUri: Uri | undefined) => { if (fileUri) { this.writeFile(fileUri.fsPath, content); } }); - } - else { - vscode.window.showInputBox({ - prompt: "Filename", + } else { + window.showInputBox({ placeHolder: `Enter a filename (${defaultFileName}${exportType} or .xyz).`, + prompt: "Filename", value: defaultFileName + exportType - }).then((fileName: string) => { + }).then((fileName: string | undefined) => { if (!fileName) { return; } - let fileExtension: any = (/[.]/.exec(fileName)) ? /[^.]+$/.exec(fileName) : undefined; - if (!fileExtension) { + if (!/[.]/.exec(fileName)) { fileName += exportType; } - if (fileName.startsWith(".")) { + if (fileName.startsWith(".")) { fileName = defaultFileName + fileName; } - let file: string = path.resolve(vscode.window.activeTextEditor.document.uri.fsPath, `../${fileName}`); - - this.writeFile(file, content); + this.writeFile(resolvePath(getPath(), `../${fileName}`), content); }); } }); } - private writeFile(file: string, content: string): void - { - fs.writeFile(file, content, (err: NodeJS.ErrnoException) => { - if (err) { - vscode.window.showErrorMessage(`Could not save the file: ${err}`); - } - else { - vscode.window.showInformationMessage(`File saved as ${path.basename(file)}`); + private writeFile(file: string, content: string): void { + writeFile(file, content, (error: NodeJS.ErrnoException) => { + if (error) { + window.showErrorMessage(`Could not save the file: ${error.message}`); + } else { + window.showInformationMessage(`File saved as ${basename(file)}`); } }); } diff --git a/src/extension.ts b/src/extension.ts index 5018426..4ba991d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,108 +1,55 @@ -"use strict"; - -import * as vscode from "vscode"; -import * as path from "path"; - -import * as npm from "npm"; -import * as phantomJS from "phantomjs-prebuilt"; +import { ExtensionContext, TextDocument, window, workspace } from "vscode"; import Beautify from "./beautify"; -import CopyHTML from "./copy"; +import Copy from "./copy"; import Documentation from "./documentation"; -import SendEmail from "./email"; -import ExportHTML from "./export"; -import LintingProvider from "./linter"; +import Email from "./email"; +import Export from "./export"; +import Linter from "./linter"; import Migrate from "./migrate"; -import PreviewManager from "./preview"; +import Preview from "./preview"; import Screenshot from "./screenshot"; import Template from "./template"; - -import helper from "./helper"; - -let beautify: Beautify; -let copyHTML: CopyHTML; -let documentation: Documentation; -let sendEmail: SendEmail; -let exportHTML: ExportHTML; -let linter: LintingProvider; -let migrate: Migrate; -let previewManager: PreviewManager; -let screenshot: Screenshot; -let template: Template; - -export function activate(context: vscode.ExtensionContext) { - // Gets a value indicating whether PhantomJS could be built - let phantomJSBuilt: any = undefined; - - // Rebuilding PhantomJS if required - if (phantomJS.platform != process.platform) { - try { - let env: NodeJS.ProcessEnv = process.env; - env["PHANTOMJS_PLATFORM"] = process.platform; - env["PHANTOMJS_ARCH"] = process.arch; - - vscode.window.showInformationMessage("MJML needs to be rebuilt for your current platform. Please wait for the installation to finish..."); - process.chdir(path.join(__dirname, "..")); - - npm.load({ - loglevel: "silent" - }, (err: any) => { - npm.commands.rebuild(["phantomjs-prebuilt"], (err: any, done: any) => { - if (!err) { - phantomJSBuilt = true; - vscode.window.showInformationMessage("MJML's been updated. Please restart VSCode in order to continue using MJML."); - } - else { - vscode.window.showErrorMessage("MJML couldn't build the propper version of PhantomJS. Restart VSCode in order to try it again."); - } - - screenshot = new Screenshot(context, process.platform, phantomJS.platform, phantomJSBuilt); - }); - }); - } - catch (err) { - vscode.window.showErrorMessage("MJML couldn't build the propper version of PhantomJS. Restart VSCode in order to try it again."); - phantomJSBuilt = false; - } - } - else { - screenshot = new Screenshot(context, process.platform, phantomJS.platform, phantomJSBuilt); - } +import Version from "./version"; + +import { isMJMLFile } from "./helper"; + +let context: ExtensionContext; +let extensionFeatures: object[] = []; + +export function activate(extensionContext: ExtensionContext) { + context = extensionContext; + + extensionFeatures = [ + new Beautify(context.subscriptions), + new Copy(context.subscriptions), + new Documentation(context), + new Email(context.subscriptions), + new Export(context.subscriptions), + new Linter(context.subscriptions), + new Migrate(context.subscriptions), + new Preview(context), + new Screenshot(context.subscriptions), + new Template(context), + new Version(context.subscriptions) + ]; // Detect MJML 3 - vscode.workspace.onDidOpenTextDocument((document?: vscode.TextDocument) => { - if (document) { - if (helper.isMJMLFile(document)) { - if (document.getText().indexOf("mj-container") > -1) { - vscode.window.showInformationMessage(`MJML v3 syntax detected. Use "MJML: Migrate" to get the migrated MJML.`); - } - } + workspace.onDidOpenTextDocument((document?: TextDocument) => { + if (document && isMJMLFile(document) && document.getText().indexOf("mj-container") > -1) { + window.showInformationMessage(`MJML v3 syntax detected. Use "MJML: Migrate" to get the migrated MJML.`); } }, null, context.subscriptions); - - if (vscode.workspace.getConfiguration("mjml").lintEnable) { - linter = new LintingProvider(context.subscriptions); - } - - beautify = new Beautify(context.subscriptions); - vscode.languages.registerDocumentFormattingEditProvider({ - scheme: "file", - language: "mjml" - }, { - provideDocumentFormattingEdits(document: vscode.TextDocument): vscode.TextEdit[] { - return beautify.formatDocument(); - } - }); - - copyHTML = new CopyHTML(context.subscriptions); - documentation = new Documentation(context); - sendEmail = new SendEmail(context.subscriptions); - exportHTML = new ExportHTML(context.subscriptions); - migrate = new Migrate(context.subscriptions); - previewManager = new PreviewManager(context); - template = new Template(context.subscriptions); } export function deactivate() { - previewManager.dispose(); + for (const feature of extensionFeatures) { + if (typeof (feature as any).dispose === "function") { + (feature as any).dispose(); + } + } + + for (const subscription of context.subscriptions) { + subscription.dispose(); + } } diff --git a/src/helper.ts b/src/helper.ts index eb6f849..3efb8db 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -1,127 +1,136 @@ -"use strict"; - -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; - -import * as beautifyJS from "js-beautify"; -import * as mime from "mime"; -import mjml2html = require("mjml"); - -export default class Helper { +import { existsSync, readFileSync, statSync } from "fs"; +import { basename, dirname, join as joinPath, parse as parsePath } from "path"; +import { TextDocument, TextEditor, window, workspace } from "vscode"; + +import { html as jsBeautify } from "js-beautify"; +import { getExtension, getType as getMimeType } from "mime"; +import mjml2html from "mjml"; + +export function renderMJML(cb: (content: string) => any, fixImg?: boolean, minify?: boolean, beautify?: boolean): void { + const activeTextEditor: TextEditor | undefined = window.activeTextEditor; + if (!activeTextEditor) { + return; + } - static renderMJML(cb: (content: string) => any, fixLinks?: boolean, minify?: boolean, beautify?: boolean): any { - if (!(this.isMJMLFile(vscode.window.activeTextEditor.document))) { - vscode.window.showWarningMessage("This is not a MJML document!"); - return; - } + if (!isMJMLFile(activeTextEditor.document)) { + window.showWarningMessage("This is not a MJML document!"); - let content: string = this.mjml2html( - vscode.window.activeTextEditor.document.getText(), - minify != undefined ? minify : vscode.workspace.getConfiguration("mjml").minifyHtmlOutput, - beautify != undefined ? beautify : vscode.workspace.getConfiguration("mjml").beautifyHtmlOutput, - ).html; + return; + } - if (content) { - if (fixLinks != undefined && fixLinks) { - content = this.fixLinks(content); - } + let content: string = mjmlToHtml( + activeTextEditor.document.getText(), + minify !== undefined ? minify : workspace.getConfiguration("mjml").minifyHtmlOutput, + beautify !== undefined ? beautify : workspace.getConfiguration("mjml").beautifyHtmlOutput + ).html; - return cb(content); + if (content) { + if (fixImg !== undefined && fixImg) { + content = fixImages(content, getPath()); } - else { - vscode.window.showErrorMessage(`MJMLError: Failed to parse file ${path.basename(vscode.window.activeTextEditor.document.uri.fsPath)}`); - } - } - static isMJMLFile(document: vscode.TextDocument): boolean { - return document.languageId === "mjml" && document.uri.scheme !== "mjml-preview"; + return cb(content); + } else { + window.showErrorMessage(`MJMLError: Failed to parse file ${basename(getPath())}`); } +} - static mjml2html(mjml: string, minify: boolean, beautify: boolean, mjmlPath?: string, level: "skip" | "strict" | "ignore" = "skip" ): { html: string, errors: any[] } { - try { - if (!mjmlPath) { - mjmlPath = this.getPath(); - } +export function isMJMLFile(document: TextDocument): boolean { + return document.languageId === "mjml" && (document.uri.scheme === "file" || document.uri.scheme === "untitled"); +} - return mjml2html(mjml, { - level: level, - minify: minify, - beautify: beautify, - filePath: mjmlPath, - mjmlConfigPath: this.getCWD(mjmlPath) - }); - } - catch (err) { - return { html: "", errors: [err] }; +export function mjmlToHtml( + mjml: string, minify: boolean, beautify: boolean, path?: string, validation: "strict" | "soft" | "skip" = "skip" +): { html: string, errors: any[] } { + try { + if (!path) { + path = getPath(); } - } - static getCWD(mjmlPath?: string): string { - if (vscode.workspace.rootPath) { - return vscode.workspace.rootPath; - } - else { - return (mjmlPath) ? path.parse(mjmlPath).dir : ""; - } + return mjml2html(mjml, { + beautify, + filePath: path, + minify, + mjmlConfigPath: getCWD(path), + validationLevel: validation + }); + } catch (error) { + return { html: "", errors: [error] }; } +} - static encodeImage(filePath: string, original: string): string { - let mimeType: string = mime.getType(filePath); - if (!mimeType || ["bmp", "gif", "jpeg", "jpg", "png", "svg"].indexOf(mime.getExtension(mimeType)) == -1) { - return original; +export function fixImages(text: string, mjmlPath: string): string { + return text.replace( + new RegExp(/((?:src|url)(?:=|\()(?:[\'\"]|))((?!http|\\|"|#).+?)([\'\"]|\))/, "gmi"), + (_1: string, start: string, src: string, end: string): string => { + return start + encodeImage(joinPath(dirname(mjmlPath), src), src) + end; } + ); +} - if (filePath && fs.existsSync(filePath) && fs.statSync(filePath).isFile()) { - let data: Buffer = fs.readFileSync(filePath); - if (data) { - return `data:${mimeType};base64,${data.toString("base64")}`; +export function beautifyHTML(mjml: string): string | undefined { + try { + const replaced: string = mjml.replace( + new RegExp(/<.*mj-style[^>]*>(?:[^<>]+)<.*\/.*mj-style>/, "gmi"), (style: string): string => { + return style.replace(/mj-style/gi, "style"); } + ); + + const beautified: string = jsBeautify(replaced, workspace.getConfiguration("mjml").beautify); + + if (replaced !== mjml) { + return beautified.replace( + new RegExp(/<.*style[^>]*>(?:[^<>]+)<.*\/.*style>/, "gmi"), (styleBlock: string): string => { + return styleBlock.replace( + new RegExp(/<.*style.*>/, "gi"), (style: string): string => { + return style.replace("style", "mj-style"); + } + ); + } + ); } - return original; + return beautified; + } catch (error) { + window.showErrorMessage(error); + + return; } +} - static fixLinks(text: string, mjmlPath?: string): string { - return text.replace( - new RegExp(/((?:src|href|url)(?:=|\()(?:[\'\"]|))((?!http|\\|"|#).+?)([\'\"]|\))/, "gmi"), - (subString: string, p1: string, p2: string, p3: string): string => { - return [p1, this.encodeImage(path.join(path.dirname(((mjmlPath) ? mjmlPath : this.getPath())), p2), p2), p3].join(""); - } - ); +export function getPath(): string { + if (window.activeTextEditor && window.activeTextEditor.document) { + return window.activeTextEditor.document.uri.fsPath; } - static beautifyHTML(mjml: string): any { - try { - mjml = beautifyJS.html(mjml.replace(/mj-style/g, "style"), vscode.workspace.getConfiguration("mjml").beautify); - let tmp: RegExpExecArray = /<.*mj-head.*>[\s\S]+<.*\/.*mj-head.*>/gim.exec(mjml); + return ""; +} - return mjml.replace(tmp[0], tmp[0].replace(/style/gi, "mj-style")); - } catch (err) { - vscode.window.showErrorMessage(err); - return; - } +function getCWD(mjmlPath?: string): string { + if (workspace.rootPath) { + return workspace.rootPath; } - static setBackgroundColor(html: string): string { - if (vscode.workspace.getConfiguration("mjml").previewBackgroundColor) { - let tmp: RegExpExecArray = /<.*head.*>/i.exec(html); + return (mjmlPath) ? parsePath(mjmlPath).dir : ""; +} - if (tmp && tmp[0]) { - html = html.replace(tmp[0], `${tmp[0]}\n`); - } - } +function encodeImage(filePath: string, original: string): string { + const mimeType: string | null = getMimeType(filePath); + if (!mimeType) { + return original; + } - return html; + const extension: string | null = getExtension(mimeType); + if (!extension || ["bmp", "gif", "jpeg", "jpg", "png", "svg"].indexOf(extension) === -1) { + return original; } - static getPath(): string { - if (vscode.window.activeTextEditor.document) { - return vscode.window.activeTextEditor.document.uri.fsPath; - } - else { - return ""; + if (filePath && existsSync(filePath) && statSync(filePath).isFile()) { + const data: Buffer = readFileSync(filePath); + if (data) { + return `data:${mimeType};base64,${data.toString("base64")}`; } } + return original; } diff --git a/src/linter.ts b/src/linter.ts index 997b31d..d7c3b32 100644 --- a/src/linter.ts +++ b/src/linter.ts @@ -1,78 +1,87 @@ -"use strict"; - -import * as vscode from "vscode"; - -import helper from "./helper"; - -export default class MJMLLintingProvider { - - private command: vscode.Disposable; - private diagnosticCollection: vscode.DiagnosticCollection; - - constructor(subscriptions: vscode.Disposable[]) { - this.diagnosticCollection = vscode.languages.createDiagnosticCollection(); - - vscode.window.onDidChangeActiveTextEditor((editor?: vscode.TextEditor) => { - if (editor) { - if (helper.isMJMLFile(editor.document)) { - this.doMJMllint(editor.document); - } - } - }, this, subscriptions); - - vscode.workspace.onDidChangeTextDocument((event: vscode.TextDocumentChangeEvent) => { - if (vscode.workspace.getConfiguration("mjml").lintWhenTyping) { - this.doMJMllint(event.document); - } - }, this, subscriptions); - - vscode.workspace.onDidOpenTextDocument(this.doMJMllint, this, subscriptions); - vscode.workspace.onDidSaveTextDocument(this.doMJMllint, this, subscriptions); - - vscode.workspace.onDidCloseTextDocument((document: vscode.TextDocument) => { - this.diagnosticCollection.delete(document.uri); - }, null, subscriptions); - - // Lint all open mjml documents - vscode.workspace.textDocuments.forEach(this.doMJMllint, this); +import { Diagnostic, DiagnosticCollection, DiagnosticSeverity, Disposable, languages, Position, Range, TextDocument, TextDocumentChangeEvent, TextEditor, window, workspace } from "vscode"; + +import { getPath, mjmlToHtml } from "./helper"; + +export default class Linter { + + private diagnosticCollection!: DiagnosticCollection; + + constructor(subscriptions: Disposable[]) { + if (workspace.getConfiguration("mjml").lintEnable) { + this.diagnosticCollection = languages.createDiagnosticCollection("mjml"); + + subscriptions.push( + this.diagnosticCollection, + + window.onDidChangeActiveTextEditor((editor?: TextEditor) => { + if (editor && editor.document) { + this.lintDocument(editor.document); + } + }), + + workspace.onDidChangeTextDocument((event?: TextDocumentChangeEvent) => { + if (event && event.document && workspace.getConfiguration("mjml").lintWhenTyping) { + this.lintDocument(event.document); + } + }), + + workspace.onDidCloseTextDocument((document?: TextDocument) => { + if (document) { + this.diagnosticCollection.delete(document.uri); + } + }), + + workspace.onDidOpenTextDocument((document?: TextDocument) => { + if (document) { + this.lintDocument(document); + } + }), + + workspace.onDidSaveTextDocument((document?: TextDocument) => { + if (document) { + this.lintDocument(document); + } + }) + ); + + // Lint all open mjml documents + workspace.textDocuments.forEach(this.lintDocument, this); + } } public dispose(): void { this.diagnosticCollection.clear(); this.diagnosticCollection.dispose(); - this.command.dispose(); } - private doMJMllint(textDocument: vscode.TextDocument): void { + private lintDocument(textDocument: TextDocument): void { if (textDocument.languageId !== "mjml") { return; } - let diagnostics: vscode.Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; try { - let filePath: string = helper.getPath(); - let { html, errors } = helper.mjml2html(vscode.window.activeTextEditor.document.getText(), false, false, filePath, "strict"); - - errors.forEach((err: any) => { - let line: number = err.line - 1; - let currentLine: string = vscode.window.activeTextEditor.document.lineAt(line).text; - - let start: vscode.Position = new vscode.Position(line, currentLine.indexOf("<")); - let end: vscode.Position = new vscode.Position(line, currentLine.length); - - let diagnostic: vscode.Diagnostic = new vscode.Diagnostic( - new vscode.Range(start, end), - err.message, - vscode.DiagnosticSeverity.Error - ); - - diagnostics.push(diagnostic); - }); + const errors: any = mjmlToHtml(textDocument.getText(), false, false, getPath(), "strict").errors; + + if (errors && errors[0]) { + errors[0].errors.forEach((error: any) => { + const line: number = error.line - 1; + const currentLine: string = textDocument.lineAt(line).text; + + diagnostics.push(new Diagnostic( + new Range( + new Position(line, currentLine.indexOf("<")), + new Position(line, currentLine.length) + ), + error.message, + DiagnosticSeverity.Error + )); + }); + } this.diagnosticCollection.set(textDocument.uri, diagnostics); - } - catch (err) { + } catch (error) { this.diagnosticCollection.set(textDocument.uri, diagnostics); } } diff --git a/src/migrate.ts b/src/migrate.ts index f8037d7..a060f53 100644 --- a/src/migrate.ts +++ b/src/migrate.ts @@ -1,56 +1,61 @@ -"use strict"; - -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; +import { writeFile } from "fs"; +import { basename, resolve as resolvePath } from "path"; +import { commands, Disposable, TextEditor, window } from "vscode"; import migrate from "mjml-migrate"; -import helper from "./helper"; +import { beautifyHTML, getPath, isMJMLFile } from "./helper"; export default class Migrate { - constructor(subscriptions: vscode.Disposable[]) { + constructor(subscriptions: Disposable[]) { subscriptions.push( - vscode.commands.registerCommand("mjml.migrate", () => { + commands.registerCommand("mjml.migrate", () => { this.migrate(); }) ); } private migrate(): void { - if (!(helper.isMJMLFile(vscode.window.activeTextEditor.document))) { - vscode.window.showWarningMessage("This is not a MJML document!"); + const activeTextEditor: TextEditor | undefined = window.activeTextEditor; + if (!activeTextEditor) { + return; + } + + if (!isMJMLFile(activeTextEditor.document)) { + window.showWarningMessage("This is not a MJML document!"); + return; } try { - let mjml: string = migrate(vscode.window.activeTextEditor.document.getText()); - - if (mjml) { - let inputFileName: string = path.basename(vscode.window.activeTextEditor.document.uri.fsPath); - let fileName: string = inputFileName.replace(/\.[^\.]+$/, ""); - let file: string = path.resolve(vscode.window.activeTextEditor.document.uri.fsPath, `../${fileName}_v4.mjml`); - - let content: string = helper.beautifyHTML(mjml); - - if (content) { - fs.writeFile(file, content, (err: NodeJS.ErrnoException) => { - if (err) { - vscode.window.showErrorMessage(err.message); - } - else { - vscode.window.showInformationMessage(`${inputFileName} was converted to the MJML 4 syntax in ${fileName}_v4.mjml`); - } - }); - } - else { - vscode.window.showErrorMessage("Something went wrong."); - } + const mjml: string = migrate(activeTextEditor.document.getText()); + if (!mjml) { + return; } - } - catch (err) { - vscode.window.showErrorMessage("Input file failed to render."); + + const inputFileName: string = basename(getPath()); + const fileName: string = inputFileName.replace(/\.[^\.]+$/, ""); + const file: string = resolvePath(getPath(), `../${fileName}_v4.mjml`); + + const content: string | undefined = beautifyHTML(mjml); + + if (content) { + writeFile(file, content, (error: NodeJS.ErrnoException) => { + if (error) { + window.showErrorMessage(error.message); + } else { + window.showInformationMessage( + `${inputFileName} was converted to the MJML 4 syntax in ${fileName}_v4.mjml` + ); + } + }); + } else { + window.showErrorMessage("Something went wrong."); + } + } catch (error) { + window.showErrorMessage("Input file failed to render."); + return; } } diff --git a/src/preview.ts b/src/preview.ts index cf70918..147b656 100644 --- a/src/preview.ts +++ b/src/preview.ts @@ -1,86 +1,85 @@ -"use strict"; +import { basename } from "path"; +import { commands, Disposable, ExtensionContext, TextDocument, TextDocumentChangeEvent, TextEditor, ViewColumn, WebviewPanel, window, workspace } from "vscode"; -import * as vscode from "vscode"; -import * as path from "path"; +import { fixImages, isMJMLFile, mjmlToHtml } from "./helper"; -import helper from "./helper"; +export default class Preview { -export default class PreviewManager { - - private webview: vscode.WebviewPanel | undefined; - private subscriptions: vscode.Disposable[]; - private previewOpen: boolean = false; private openedDocuments: string[] = []; + private previewOpen: boolean = false; + private subscriptions: Disposable[]; + private webview: WebviewPanel | undefined; - constructor(context: vscode.ExtensionContext) { + constructor(context: ExtensionContext) { this.subscriptions = context.subscriptions; this.subscriptions.push( - vscode.commands.registerCommand("mjml.previewToSide", () => { - this.previewOpen = true; - this.displayWebView(this.getWebviewContent()); + commands.registerCommand("mjml.previewToSide", () => { + if (window.activeTextEditor) { + this.previewOpen = true; + this.displayWebView(window.activeTextEditor.document); + } else { + window.showErrorMessage("Active editor doesn't show a MJML document."); + } }), - vscode.workspace.onDidOpenTextDocument((document?: vscode.TextDocument) => { - if (this.previewOpen && vscode.workspace.getConfiguration("mjml").autoPreview) { - if (document) { - if (document.languageId == "mjml") { - this.displayWebView(this.getWebviewContent(document)); - } - } + workspace.onDidOpenTextDocument((document?: TextDocument) => { + if (document && this.previewOpen && workspace.getConfiguration("mjml").autoPreview) { + this.displayWebView(document); } }), - vscode.window.onDidChangeActiveTextEditor((editor?: vscode.TextEditor) => { - if (this.previewOpen && vscode.workspace.getConfiguration("mjml").autoPreview) { - if (editor) { - if (editor.document.languageId == "mjml") { - this.displayWebView(this.getWebviewContent(editor.document)); - } - } + window.onDidChangeActiveTextEditor((editor?: TextEditor) => { + if (editor && this.previewOpen && workspace.getConfiguration("mjml").autoPreview) { + this.displayWebView(editor.document); } }), - vscode.workspace.onDidCloseTextDocument((document?: vscode.TextDocument) => { - if (this.previewOpen) { - if (document) { - this.removeDocument(document.fileName); - - if (this.openedDocuments.length == 0 && vscode.workspace.getConfiguration("mjml").autoClosePreview) { - this.webview.dispose(); - } - } + workspace.onDidChangeTextDocument((event?: TextDocumentChangeEvent) => { + if (event && this.previewOpen && workspace.getConfiguration("mjml").updateWhenTyping) { + this.displayWebView(event.document); } }), - vscode.workspace.onDidChangeTextDocument((event?: vscode.TextDocumentChangeEvent) => { - if (this.previewOpen && vscode.workspace.getConfiguration("mjml").updateWhenTyping) { - if (event) { - if (event.document.languageId == "mjml") { - this.displayWebView(this.getWebviewContent(event.document)); - } - } + workspace.onDidSaveTextDocument((document?: TextDocument) => { + if (document && this.previewOpen) { + this.displayWebView(document); } }), - vscode.workspace.onDidSaveTextDocument((document?: vscode.TextDocument) => { - if (this.previewOpen && document) { - if (document.languageId == "mjml") { - this.displayWebView(this.getWebviewContent(document)); + workspace.onDidCloseTextDocument((document?: TextDocument) => { + if (document && this.previewOpen && this.webview) { + this.removeDocument(document.fileName); + + if (this.openedDocuments.length === 0 && workspace.getConfiguration("mjml").autoClosePreview) { + this.dispose(); } } }) ); } - private displayWebView(content: string): void { - let label: string = "MJML Preview"; - if (vscode.window.activeTextEditor.document) { - label = `MJML Preview - ${path.basename(vscode.window.activeTextEditor.document.fileName)}`; + public dispose(): void { + if (this.webview !== undefined) { + this.webview.dispose(); } + } + + private displayWebView(document: TextDocument): void { + if (!isMJMLFile(document)) { + return; + } + + const activeTextEditor: TextEditor | undefined = window.activeTextEditor; + if (!activeTextEditor || !activeTextEditor.document) { + return; + } + + const content: string = this.getContent(document); + const label: string = `MJML Preview - ${basename(activeTextEditor.document.fileName)}`; if (!this.webview) { - this.webview = vscode.window.createWebviewPanel("mjml-preview", label, vscode.ViewColumn.Two, { + this.webview = window.createWebviewPanel("mjml-preview", label, ViewColumn.Two, { retainContextWhenHidden: true }); @@ -91,59 +90,54 @@ export default class PreviewManager { this.previewOpen = false; }, null, this.subscriptions); - if (vscode.workspace.getConfiguration("mjml").preserveFocus) { + if (workspace.getConfiguration("mjml").preserveFocus) { // Preserve focus of Text Editor after preview open - vscode.window.showTextDocument(vscode.window.activeTextEditor.document, vscode.ViewColumn.One); + window.showTextDocument(activeTextEditor.document, ViewColumn.One); } - } - else { + } else { this.webview.title = label; this.webview.webview.html = content; } } - private getWebviewContent(document?: vscode.TextDocument): string { - let previewDocument: vscode.TextDocument; - if (document) { - previewDocument = document; - } - else { - previewDocument = vscode.window.activeTextEditor.document; - } - - let html: string = helper.mjml2html(previewDocument.getText(), false, false, previewDocument.uri.fsPath, "skip").html; + private getContent(document: TextDocument): string { + const html: string = mjmlToHtml(document.getText(), false, false, document.uri.fsPath, "skip").html; if (html) { - this.addDocument(previewDocument.fileName); + this.addDocument(document.fileName); - return helper.setBackgroundColor(helper.fixLinks(html, previewDocument.uri.fsPath)); + return this.setBackgroundColor(fixImages(html, document.uri.fsPath)); } return this.error("Active editor doesn't show a MJML document."); } + private setBackgroundColor(html: string): string { + if (workspace.getConfiguration("mjml").previewBackgroundColor) { + const tmp: RegExpExecArray | null = /<.*head.*>/i.exec(html); + + if (tmp && tmp[0]) { + html = html.replace(tmp[0], `${tmp[0]}\n`); + } + } + + return html; + } + private error(error: string): string { return `${error}`; } private addDocument(fileName: string): void { - if (this.openedDocuments.indexOf(fileName) == -1) { + if (this.openedDocuments.indexOf(fileName) === -1) { this.openedDocuments.push(fileName); } } private removeDocument(fileName: string): void { - this.openedDocuments = this.openedDocuments.filter(e => e !== fileName); - } - - public dispose(): void { - if (this.webview !== undefined) { - this.webview.dispose(); - } - - for (let s of this.subscriptions) { - s.dispose(); - } + this.openedDocuments = this.openedDocuments.filter((file: string) => file !== fileName); } } diff --git a/src/screenshot.ts b/src/screenshot.ts index d33b83e..c7b6999 100644 --- a/src/screenshot.ts +++ b/src/screenshot.ts @@ -1,151 +1,205 @@ -"use strict"; +import { basename, join as joinPath, resolve as resolvePath } from "path"; +import { commands, Disposable, ProgressLocation, Uri, window, workspace } from "vscode"; -import * as vscode from "vscode"; -import * as path from "path"; +import { commands as npmCommands, load as load } from "npm"; +import * as phantom from "phantom"; +import { platform as phantomJs } from "phantomjs-prebuilt"; -import * as webshot from "ab-webshot"; - -import helper from "./helper"; +import { getPath, renderMJML } from "./helper"; export default class Screenshot { - private processPlatform: string; - private phantomJsPlatform: string; - private phantomJSBuilt: any; - - constructor(context: vscode.ExtensionContext, processPlatform: string, phantomJsPlatform: string, phantomJSBuilt: any) { - this.processPlatform = processPlatform; - this.phantomJsPlatform = phantomJsPlatform; - this.phantomJSBuilt = phantomJSBuilt; - - context.subscriptions.push( - vscode.commands.registerCommand("mjml.screenshot", () => { - this.renderMJML(false); - }), + // Gets a value indicating whether PhantomJS could be built + private phantomJSBuilt: any = undefined; + private phantomJsPlatform: string = ""; + private processPlatform: string = ""; + + constructor(subscriptions: Disposable[]) { + // Rebuilding PhantomJS if required + if (phantomJs !== process.platform) { + this.rebuild(); + } else { + this.phantomJsPlatform = phantomJs; + this.processPlatform = process.platform; + + subscriptions.push( + commands.registerCommand("mjml.screenshot", () => { + this.renderMJML(false); + }), + + commands.registerCommand("mjml.multipleScreenshots", () => { + this.renderMJML(true); + }) + ); + } + } - vscode.commands.registerCommand("mjml.multipleScreenshots", () => { - this.renderMJML(true); - }) - ); + private async rebuild(): Promise { + await window.withProgress({ + cancellable: false, + location: ProgressLocation.Notification, + title: `MJML needs to be rebuilt for your current platform. Please wait for the installation to finish...` + }, async () => { + return new Promise((resolve, reject) => { + process.chdir(joinPath(__dirname, "..")); + + load({ + loglevel: "silent" + }, () => { + npmCommands.rebuild(["phantomjs-prebuilt"], (error: any) => { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); + }).then(() => { + this.phantomJSBuilt = true; + window.showInformationMessage( + "MJML's been updated. Please restart VSCode in order to continue using MJML." + ); + }).catch(() => { + this.phantomJSBuilt = false; + window.showErrorMessage( + "MJML couldn't build the proper version of PhantomJS. Restart VSCode in order to try it again." + ); + }); + }); } private renderMJML(multiple: boolean): void { - if (this.phantomJsPlatform != this.processPlatform || this.phantomJSBuilt != undefined) { + if (this.phantomJsPlatform !== this.processPlatform || this.phantomJSBuilt !== undefined) { if (this.phantomJSBuilt) { - vscode.window.showInformationMessage("MJML's been updated. Please restart VSCode in order to continue using MJML."); - } - else { - vscode.window.showWarningMessage("MJML couldn't build the propper version of PhantomJS. Restart VSCode in order to try it again."); + window.showInformationMessage( + "MJML's been updated. Please restart VSCode in order to continue using MJML." + ); + } else { + window.showWarningMessage( + "MJML couldn't build the proper version of PhantomJS. Restart VSCode in order to try it again." + ); } - } - else { - helper.renderMJML((content: string) => { - let defaultWidth: number = vscode.workspace.getConfiguration("mjml").screenshotWidth; - - if (!multiple) { - vscode.window.showInputBox({ - prompt: "Width", - placeHolder: `Enter image width (${defaultWidth}px).`, - value: defaultWidth.toString() - }).then((width: any) => { - if (!width) { - return; - } - - width = parseInt(width.replace(/[^0-9\.]+/g, "")); - if (!width || Number.isNaN(parseInt(width))) { - width = defaultWidth; - } + } else { + renderMJML((content: string) => { + let defaultWidth: string = workspace.getConfiguration("mjml").screenshotWidth.toString(); + + let placeHolder: string = `Enter image width (${defaultWidth}).`; + if (multiple) { + defaultWidth = workspace.getConfiguration("mjml").screenshotWidths.join(", "); + placeHolder = `Comma-separated list of image widths (${defaultWidth}).`; + } - this.showSaveDialog(multiple, content, width); + window.showInputBox({ + placeHolder, + prompt: "Width", + value: defaultWidth + }).then((width: string | undefined) => { + if (!width) { + return; + } + + const imgWidth: Array = width.split(",").map((tmpWidth: string) => { + return (tmpWidth) ? parseInt(tmpWidth, 10) : undefined; + }).filter((tmpWidth: number | undefined) => { + return (tmpWidth) ? tmpWidth : undefined; }); - } - else { - this.showSaveDialog(multiple, content, defaultWidth); - } + + if (imgWidth.length > 0) { + this.showSaveDialog(multiple, content, imgWidth); + } + }); }, true); } } - private showSaveDialog(multiple: boolean, content: string, width: number): void { - let defaultFileName: string = path.basename(vscode.window.activeTextEditor.document.uri.fsPath).replace(/\.[^\.]+$/, ""); + private showSaveDialog(multiple: boolean, content: string, width: Array): void { + const defaultFileName: string = basename(getPath()).replace(/\.[^\.]+$/, ""); let screenshotType: string = "png"; - if (["png", "jpg", "jpeg"].indexOf(vscode.workspace.getConfiguration("mjml").screenshotType)) { - screenshotType = vscode.workspace.getConfiguration("mjml").screenshotType; + if (["png", "jpg", "jpeg"].indexOf(workspace.getConfiguration("mjml").screenshotType)) { + screenshotType = workspace.getConfiguration("mjml").screenshotType; } - if (vscode.workspace.getConfiguration("mjml").showSaveDialog) { - vscode.window.showSaveDialog({ - defaultUri: vscode.Uri.file(path.resolve(vscode.window.activeTextEditor.document.uri.fsPath, `../${defaultFileName}.${screenshotType}`)), + if (workspace.getConfiguration("mjml").showSaveDialog) { + window.showSaveDialog({ + defaultUri: Uri.file(resolvePath(getPath(), `../${defaultFileName}.${screenshotType}`)), filters: { Images: ["png", "jpg", "jpeg"] } - }).then((fileUri: vscode.Uri) => { + }).then((fileUri: Uri | undefined) => { if (fileUri) { - this.takeScreenshot(multiple, fileUri.fsPath, content, width, screenshotType); + this.screenshot(multiple, fileUri.fsPath, content, width, screenshotType); } }); - } - else { - vscode.window.showInputBox({ - prompt: "Filename", + } else { + window.showInputBox({ placeHolder: "Enter a filename.", - value: defaultFileName + "." + screenshotType - }).then((fileName: string) => { + prompt: "Filename", + value: `${defaultFileName}.${screenshotType}` + }).then((fileName: string | undefined) => { if (!fileName) { return; } fileName = fileName ? fileName.replace(/\.[^\.]+$/, "") : defaultFileName; - let file: string = path.resolve(vscode.window.activeTextEditor.document.uri.fsPath, `../${fileName}.${screenshotType}`); + const file: string = resolvePath(getPath(), `../${fileName}.${screenshotType}`); - this.takeScreenshot(multiple, file, content, width, screenshotType); + this.screenshot(multiple, file, content, width, screenshotType); }); } } - private takeScreenshot(multiple: boolean, file: string, content: string, width: any, screenshotType: string): void { - if (multiple) { - let width: (string | number)[] = vscode.workspace.getConfiguration("mjml").screenshotWidths; - let fileName: string = path.basename(file).split(".").slice(0, -1).join("."); + private async screenshot( + multiple: boolean, file: string, html: string, width: Array, type: string + ): Promise { + await window.withProgress({ + cancellable: false, + location: ProgressLocation.Notification, + title: `Taking ${((multiple) ? "screenshots" : "screenshot")}...` + }, async () => { + try { + const instance = await phantom.create(); + const page = await instance.createPage(); + + await page.setContent(html, ""); + await page.reload(); + + for (const imgWidth of width) { + if (imgWidth && Number.isInteger(imgWidth)) { + let filePath: string; + let imageName: string; + + if (multiple) { + const fileName: string = + basename(file).split(".").slice(0, -1).join(".") + + "_" + + imgWidth.toString(); + filePath = resolvePath(getPath(), `../${fileName}.${type}`); + imageName = `${fileName}.${type}`; + } else { + filePath = imageName = file; + } - if (width) { - width.forEach((width: string | number) => { - let tmpFileName: string = fileName + "_" + width; - let file: string = path.resolve(vscode.window.activeTextEditor.document.uri.fsPath, `../${tmpFileName}.${screenshotType}`); + await page.property("viewportSize", { + height: 480, + width: imgWidth + }); - this.webshot(content, width, file, tmpFileName, screenshotType); - }); - } - else { - this.webshot(content, width, file, fileName, screenshotType); - } - } - else { - this.webshot(content, width, file, file, screenshotType); - } - } + await page.render(filePath, { + quality: workspace.getConfiguration("mjml").screenshotQuality + }); - private webshot(htmlDocument: string, width: any, file: string, fileName: string, screenshotType: string): void { - webshot(htmlDocument, file, { - screenSize: { - width: parseInt(width), - height: 480 - }, - shotSize: { - width: "window", - height: "all" - }, - quality: vscode.workspace.getConfiguration("mjml").screenshotQuality, - siteType: "html", - streamType: screenshotType - }, (err: any) => { - if (err) { - vscode.window.showErrorMessage(err.message); - } - else { - vscode.window.showInformationMessage(`Successfully saved screenshot ${fileName}.${screenshotType}`); + window.showInformationMessage(`Successfully saved screenshot ${imageName}`); + + if (!multiple) { + break; + } + } + } + + await instance.exit(); + } catch (error) { + window.showErrorMessage(error.message); } }); } diff --git a/src/template.ts b/src/template.ts index 7da0e82..53afdfe 100644 --- a/src/template.ts +++ b/src/template.ts @@ -1,78 +1,190 @@ -"use strict"; - -import * as vscode from "vscode"; +import { existsSync, readFileSync, statSync } from "fs"; +import { join as joinPath } from "path"; +import { commands, ExtensionContext, ProgressLocation, TextDocument, TextEditor, TextEditorEdit, Uri, ViewColumn, WebviewPanel, window, workspace } from "vscode"; import fetch from "node-fetch"; export default class Template { - private templateList: object; + private context: ExtensionContext; + private templateList: Templates[] = []; + private webview: WebviewPanel | undefined; + private webviewViewColumn: ViewColumn | undefined; + + constructor(context: ExtensionContext) { + this.context = context; - constructor(subscriptions: vscode.Disposable[]) { - subscriptions.push( - vscode.commands.registerCommand("mjml.template", () => { - this.fetchEmailTemplates(); + context.subscriptions.push( + commands.registerCommand("mjml.template", () => { + this.fetchTemplates(); }) ); } - private async fetchEmailTemplates(): Promise { + private async fetchTemplates(): Promise { + if (workspace.getConfiguration("mjml").templateGallery && this.webview) { + this.webview.reveal(this.webviewViewColumn); + + return; + } + if (!this.templateList) { - let response = await fetch("https://api.github.com/repos/mjmlio/email-templates/git/trees/master?recursive=1"); - let { tree } = await response.json(); + return; + } + + this.templateList = await window.withProgress({ + cancellable: false, + location: ProgressLocation.Notification, + title: "Fetching templates..." + }, async () => { + const response = await fetch( + "https://api.github.com/repos/mjmlio/email-templates/git/trees/master?recursive=1" + ); + const { tree } = await response.json(); if (!tree) { - vscode.window.showErrorMessage("Error occurred while fetching templates list."); + window.showErrorMessage("Error occurred while fetching templates list."); + return; } - this.templateList = tree.reduce((map, item) => { - let extract: RegExpExecArray = /.*\/([^.]*)\..*/.exec(item.path); + return await tree.reduce((map: any, item: any) => { + const extract: RegExpExecArray | null = /.*\/([^.]*)\..*/.exec(item.path); if (!item.path.startsWith("templates/") && !item.path.startsWith("thumbnails/") && !extract) { return map; } - let templateName: string = extract[1]; - if (!map[templateName]) { - map[templateName] = {}; + if (extract && extract[1]) { + const templateName: string | null = extract[1]; + if (!map[templateName]) { + map[templateName] = {}; + } + + const path: string = `https://raw.githubusercontent.com/mjmlio/email-templates/master/${item.path}`; + + if (item.path.endsWith(".mjml")) { + map[templateName].mjml = path; + map[templateName].name = templateName; + } else { + map[templateName].thumbnail = path; + } + + return map; } + }, {}); + }); + + if (workspace.getConfiguration("mjml").templateGallery) { + this.displayWebView(); + } else { + this.quickPick(); + } + } - let path: string = `https://raw.githubusercontent.com/mjmlio/email-templates/master/${item.path}`; + private quickPick(): void { + window.showQuickPick(Object.keys(this.templateList), { + placeHolder: "Choose a template" + }).then((selected: string | undefined) => { + if (!selected) { + return; + } - if (item.path.endsWith(".mjml")) { - map[templateName].mjml = path; - map[templateName].name = templateName; + this.createFile((this.templateList as any)[selected].mjml, true); + }); + } + + private displayWebView(): void { + if (!this.webview) { + this.webviewViewColumn = ViewColumn.One; + + this.webview = window.createWebviewPanel("mjml-templates", "MJML Templates", ViewColumn.One, { + enableScripts: true, + localResourceRoots: [ + Uri.parse(this.context.extensionPath) + ], + retainContextWhenHidden: true + }); + + let html: string = ""; + for (const item in this.templateList) { + if (!this.templateList.hasOwnProperty(item)) { + continue; } - else { - map[templateName].thumbnail = path; + + html += ` +
+
${this.templateList[item].name}
+
`; + } + + const galleryPath: string = joinPath(__dirname, "../resources/templates/gallery.html"); + + if (!galleryPath || !existsSync(galleryPath) || !statSync(galleryPath).isFile()) { + return; + } + + this.webview.webview.html = readFileSync(galleryPath, "utf8").replace("{{templates}}", html); + + this.webview.onDidChangeViewState(() => { + if (this.webview && this.webviewViewColumn !== this.webview.viewColumn) { + this.webviewViewColumn = this.webview.viewColumn; } + }); - return map; - }, {}); + this.webview.onDidDispose(() => { + this.webview = undefined; + this.webviewViewColumn = ViewColumn.One; + }); } - this.quickPick(); + this.handleEvents(); } - private quickPick(): void { - vscode.window.showQuickPick(Object.keys(this.templateList), { - placeHolder: "Choose a template" - }).then((selected: string) => { - if (selected) { - fetch(this.templateList[selected].mjml).then((response: any) => { - if (response.status == 200) { - return response.text(); - } - }).then((body: string) => { - if (body) { - vscode.window.activeTextEditor.edit((editBuilder: vscode.TextEditorEdit) => { - editBuilder.insert(vscode.window.activeTextEditor.selection.active, body); - }); + private handleEvents(): void { + if (this.webview) { + // Handle messages from the webview + this.webview.webview.onDidReceiveMessage((message: WebviewMessage) => { + if (message.command === "createFile") { + this.createFile(message.data, false); + } + }, undefined, this.context.subscriptions); + } + } + + private createFile(templateURL: string, activeEditor: boolean): void { + fetch(templateURL).then((response: any) => { + if (response.status === 200) { + return response.text(); + } + }).then(async (body: string) => { + if (body) { + if (activeEditor) { + const activeTextEditor: TextEditor | undefined = window.activeTextEditor; + if (!activeTextEditor) { + return; } - else { - vscode.window.showErrorMessage("Error occurred while fetching template."); + + activeTextEditor.edit((editBuilder: TextEditorEdit) => { + editBuilder.insert(activeTextEditor.selection.active, body); + }); + } else { + const document: TextDocument = await workspace.openTextDocument({ + content: body, + language: "mjml" + }); + + await window.showTextDocument(document, { + viewColumn: ViewColumn.One + }); + + if (workspace.getConfiguration("mjml").templateGalleryAutoClose && this.webview) { + this.webview.dispose(); } - }); + } + } else { + window.showErrorMessage("Error occurred while fetching template."); } }); } diff --git a/src/version.ts b/src/version.ts new file mode 100644 index 0000000..28bd895 --- /dev/null +++ b/src/version.ts @@ -0,0 +1,28 @@ +import { existsSync, readFileSync, statSync } from "fs"; +import { join as joinPath } from "path"; +import { commands, Disposable, window } from "vscode"; + +export default class Version { + + constructor(subscriptions: Disposable[]) { + subscriptions.push( + commands.registerCommand("mjml.version", () => { + this.version(); + }) + ); + } + + private version(): void { + const filePath: string = joinPath(__dirname, "../node_modules/mjml/package.json"); + + if (filePath && existsSync(filePath) && statSync(filePath).isFile()) { + try { + const data: any = JSON.parse(readFileSync(filePath, "utf8")); + window.showInformationMessage(`MJML version: ${data.version}`); + } catch (error) { + window.showErrorMessage(error.message); + } + } + } + +} diff --git a/tsconfig.json b/tsconfig.json index fcc21d2..39d2bca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,33 @@ { "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", + "alwaysStrict": true, + "forceConsistentCasingInFileNames": true, "lib": [ "es6" ], + "module": "commonjs", + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "out", + "removeComments": true, + "rootDir": "src", "sourceMap": true, - "rootDir": "src" + "strict": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "target": "es6", + "typeRoots": [ + "./node_modules/@types", + "./typings/" + ] }, "exclude": [ - "node_modules", - "documentation" + "./documentation", + "./node_modules/" ] } \ No newline at end of file diff --git a/tslint.json b/tslint.json index fd00552..5be7d29 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,61 @@ { + "extends": [ + "tslint:recommended" + ], "rules": { - "no-unused-variable": true, - "no-unused-expression": true + "class-name": true, + "curly": true, + "import-spacing": true, + "indent": [ + true, "spaces", 4 + ], + "max-line-length": [ + true, { + "limit": 120, + "ignore-pattern": "^import |^export {(.*?)}" + } + ], + "no-unused-expression": true, + "no-var-keyword": true, + "semicolon": [ + true, "always" + ], + "trailing-comma": [ + true, { + "multiline": "never", + "singleline": "never" + } + ], + "triple-equals": true, + "space-within-parens": true, + "no-irregular-whitespace": true, + "no-boolean-literal-compare": true, + "newline-before-return": true, + "linebreak-style": [ + true, "LF" + ], + "interface-name": [ + true, "never-prefix" + ], + "no-conditional-assignment": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-module", + "check-operator", + "check-preblock", + "check-rest-spread", + "check-separator", + "check-type-operator", + "check-type", + "check-typecast" + ] + }, + "linterOptions": { + "exclude": [ + "./documentation/*", + "./node_modules/*" + ] } } \ No newline at end of file diff --git a/typings/extension.d.ts b/typings/extension.d.ts new file mode 100644 index 0000000..a4a3124 --- /dev/null +++ b/typings/extension.d.ts @@ -0,0 +1,25 @@ +declare module "mjml-migrate" +declare module "mjml" +declare module "node-mailjet" +declare module "phantom" +declare module "phantomjs-prebuilt" + +declare interface WebviewMessage { + command: string; + data: string; +} + +declare interface Templates { + mjml: string; + name: string; + thumbnail: string; +} + +declare interface Attachments { + "Content-type"?: string | null; + cid?: string; + content?: any; + filename?: string; + Filename?: string; + originalPath: string; +}