소스 검색

Merge pull request #2 from DioxusLabs/jk/overhaul

Overhaul - add auto reloading, status pages, web sockets, move to Tokio/structopt
Jonathan Kelley 3 년 전
부모
커밋
0fe74f7dcc

+ 68 - 0
.github/workflows/main.yml

@@ -0,0 +1,68 @@
+on: [push, pull_request]
+
+name: Rust CI
+
+jobs:
+  check:
+    name: Check
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          override: true
+      - uses: Swatinem/rust-cache@v1
+      - uses: actions-rs/cargo@v1
+        with:
+          command: check
+
+  test:
+    name: Test Suite
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          override: true
+      - uses: Swatinem/rust-cache@v1
+      - uses: actions-rs/cargo@v1
+        with:
+          command: test
+
+  fmt:
+    name: Rustfmt
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          override: true
+      - uses: Swatinem/rust-cache@v1
+      - run: rustup component add rustfmt
+      - uses: actions-rs/cargo@v1
+        with:
+          command: fmt
+          args: --all -- --check
+
+  # clippy:
+  #  name: Clippy
+  #  runs-on: ubuntu-latest
+  #  steps:
+  #    - uses: actions/checkout@v2
+  #    - uses: actions-rs/toolchain@v1
+  #      with:
+  #        profile: minimal
+  #        toolchain: stable
+  #        override: true
+  #    - uses: Swatinem/rust-cache@v1
+  #    - run: rustup component add clippy
+  #    - uses: actions-rs/cargo@v1
+  #      with:
+  #        command: clippy
+  #        args: -- -D warnings

+ 1 - 3
.vscode/settings.json

@@ -1,3 +1 @@
-{
-    "rust-analyzer.inlayHints.enable": false
-}
+{}

+ 13 - 11
Cargo.toml

@@ -1,7 +1,7 @@
 [package]
 name = "dioxus-studio"
 version = "0.1.0"
-authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
+authors = ["Jonathan Kelley"]
 edition = "2018"
 description = "CLI tool for developing, testing, and publishing Dioxus apps"
 "license" = "MIT/Apache-2.0"
@@ -14,20 +14,22 @@ log = "0.4.13"
 fern = { version = "0.6.0", features = ["colored"] }
 wasm-bindgen-cli-support = "0.2.78"
 anyhow = "1.0.38"
-argh = "0.1.4"
-serde = "1.0.120"
-serde_json = "1.0.61"
-async-std = { version = "1.9.0", features = ["attributes"] }
-tide = "0.15.0"
-fs_extra = "1.2.0"
 
-cargo_toml = "0.8.1"
+serde = "1"
+serde_json = "1"
+
+fs_extra = "1.2.0"
+cargo_toml = "0.10.0"
 futures = "0.3.12"
 notify = "5.0.0-pre.4"
-rjdebounce = "0.2.1"
-tempfile = "3.2.0"
+html_parser = "0.6.2"
+tui = { version = "0.16.0", features = ["crossterm"] }
+crossterm = "0.22.1"
+binary-install = "0.0.2"
+convert_case = "0.5.0"
+structopt = "0.3.25"
+cargo_metadata = "0.14.1"
 
 [[bin]]
-
 path = "src/main.rs"
 name = "dioxus"

+ 11 - 0
TODO.md

@@ -0,0 +1,11 @@
+
+asd
+- [ ] use a TUI for the dev server aspect of things
+- [ ] allow any index.html
+- [ ] use wasmopt for production builds
+- [ ] pass arguments through to `cargo`
+- [ ] figure out a bundling strategy 
+- [ ] an external configuration
+
+
+should we just use trunk?

+ 20 - 0
extension/.eslintrc.js

@@ -0,0 +1,20 @@
+/**@type {import('eslint').Linter.Config} */
+// eslint-disable-next-line no-undef
+module.exports = {
+	root: true,
+	parser: '@typescript-eslint/parser',
+	plugins: [
+		'@typescript-eslint',
+	],
+	extends: [
+		'eslint:recommended',
+		'plugin:@typescript-eslint/recommended',
+	],
+	rules: {
+		'semi': [2, "always"],
+		'@typescript-eslint/no-unused-vars': 0,
+		'@typescript-eslint/no-explicit-any': 0,
+		'@typescript-eslint/explicit-module-boundary-types': 0,
+		'@typescript-eslint/no-non-null-assertion': 0,
+	}
+};

+ 13 - 0
extension/.gitignore

@@ -0,0 +1,13 @@
+.DS_Store
+npm-debug.log
+Thumbs.db
+*/node_modules/
+node_modules/
+*/out/
+out/
+*/.vs/
+.vs/
+tsconfig.lsif.json
+*.lsif
+*.db
+*.vsix

+ 24 - 0
extension/README.md

@@ -0,0 +1,24 @@
+# Dioxus VSCode Extension
+
+![Dioxus Logo](https://dioxuslabs.com/guide/images/dioxuslogo_full.png)
+
+This extension wraps functionality in Dioxus CLI to be used in your editor! Make sure the dioxus-cli is installed before using this extension.
+
+## Current commands:
+
+### Convert HTML to RSX
+Converts a selection of html to valid rsx.
+
+### Convert HTML to Dioxus Component
+
+Converts a selection of html to a valid Dioxus component with all SVGs factored out into their own module.
+
+## packaging
+
+```
+$ cd myExtension
+$ vsce package
+# myExtension.vsix generated
+$ vsce publish
+# <publisherID>.myExtension published to VS Code Marketplace
+```

+ 3025 - 0
extension/package-lock.json

@@ -0,0 +1,3025 @@
+{
+    "name": "dioxusstudio",
+    "version": "0.0.1",
+    "lockfileVersion": 2,
+    "requires": true,
+    "packages": {
+        "": {
+            "name": "dioxusstudio",
+            "version": "0.0.1",
+            "license": "MIT",
+            "devDependencies": {
+                "@types/node": "^12.12.0",
+                "@types/vscode": "^1.32.0",
+                "@typescript-eslint/eslint-plugin": "^4.16.0",
+                "@typescript-eslint/parser": "^4.16.0",
+                "eslint": "^7.21.0",
+                "typescript": "^4.3.5"
+            },
+            "engines": {
+                "vscode": "^1.32.0"
+            }
+        },
+        "node_modules/@babel/code-frame": {
+            "version": "7.12.11",
+            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+            "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+            "dev": true,
+            "dependencies": {
+                "@babel/highlight": "^7.10.4"
+            }
+        },
+        "node_modules/@babel/helper-validator-identifier": {
+            "version": "7.12.11",
+            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
+            "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
+            "dev": true
+        },
+        "node_modules/@babel/highlight": {
+            "version": "7.13.8",
+            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.8.tgz",
+            "integrity": "sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw==",
+            "dev": true,
+            "dependencies": {
+                "@babel/helper-validator-identifier": "^7.12.11",
+                "chalk": "^2.0.0",
+                "js-tokens": "^4.0.0"
+            }
+        },
+        "node_modules/@babel/highlight/node_modules/chalk": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+            "dev": true,
+            "dependencies": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/@eslint/eslintrc": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
+            "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
+            "dev": true,
+            "dependencies": {
+                "ajv": "^6.12.4",
+                "debug": "^4.1.1",
+                "espree": "^7.3.0",
+                "globals": "^12.1.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.2.1",
+                "js-yaml": "^3.13.1",
+                "minimatch": "^3.0.4",
+                "strip-json-comments": "^3.1.1"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            }
+        },
+        "node_modules/@nodelib/fs.scandir": {
+            "version": "2.1.4",
+            "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+            "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
+            "dev": true,
+            "dependencies": {
+                "@nodelib/fs.stat": "2.0.4",
+                "run-parallel": "^1.1.9"
+            },
+            "engines": {
+                "node": ">= 8"
+            }
+        },
+        "node_modules/@nodelib/fs.stat": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+            "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+            "dev": true,
+            "engines": {
+                "node": ">= 8"
+            }
+        },
+        "node_modules/@nodelib/fs.walk": {
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+            "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
+            "dev": true,
+            "dependencies": {
+                "@nodelib/fs.scandir": "2.1.4",
+                "fastq": "^1.6.0"
+            },
+            "engines": {
+                "node": ">= 8"
+            }
+        },
+        "node_modules/@types/json-schema": {
+            "version": "7.0.7",
+            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+            "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+            "dev": true
+        },
+        "node_modules/@types/node": {
+            "version": "12.12.35",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.35.tgz",
+            "integrity": "sha512-ASYsaKecA7TUsDrqIGPNk3JeEox0z/0XR/WsJJ8BIX/9+SkMSImQXKWfU/yBrSyc7ZSE/NPqLu36Nur0miCFfQ==",
+            "dev": true
+        },
+        "node_modules/@types/vscode": {
+            "version": "1.33.0",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.33.0.tgz",
+            "integrity": "sha512-JSmGiValbrcG5g20jjCfKakLiuWyrcjVezj+SEAEZ4klXQktE5EtowuGlkLVqbkiBK4iY5wy/4yW8OjecuHnjQ==",
+            "dev": true
+        },
+        "node_modules/@typescript-eslint/eslint-plugin": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.16.1.tgz",
+            "integrity": "sha512-SK777klBdlkUZpZLC1mPvyOWk9yAFCWmug13eAjVQ4/Q1LATE/NbcQL1xDHkptQkZOLnPmLUA1Y54m8dqYwnoQ==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/experimental-utils": "4.16.1",
+                "@typescript-eslint/scope-manager": "4.16.1",
+                "debug": "^4.1.1",
+                "functional-red-black-tree": "^1.0.1",
+                "lodash": "^4.17.15",
+                "regexpp": "^3.0.0",
+                "semver": "^7.3.2",
+                "tsutils": "^3.17.1"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "@typescript-eslint/parser": "^4.0.0",
+                "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/@typescript-eslint/experimental-utils": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.16.1.tgz",
+            "integrity": "sha512-0Hm3LSlMYFK17jO4iY3un1Ve9x1zLNn4EM50Lia+0EV99NdbK+cn0er7HC7IvBA23mBg3P+8dUkMXy4leL33UQ==",
+            "dev": true,
+            "dependencies": {
+                "@types/json-schema": "^7.0.3",
+                "@typescript-eslint/scope-manager": "4.16.1",
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/typescript-estree": "4.16.1",
+                "eslint-scope": "^5.0.0",
+                "eslint-utils": "^2.0.0"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "*"
+            }
+        },
+        "node_modules/@typescript-eslint/parser": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.16.1.tgz",
+            "integrity": "sha512-/c0LEZcDL5y8RyI1zLcmZMvJrsR6SM1uetskFkoh3dvqDKVXPsXI+wFB/CbVw7WkEyyTKobC1mUNp/5y6gRvXg==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/scope-manager": "4.16.1",
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/typescript-estree": "4.16.1",
+                "debug": "^4.1.1"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/@typescript-eslint/scope-manager": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
+            "integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/visitor-keys": "4.16.1"
+            },
+            "engines": {
+                "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            }
+        },
+        "node_modules/@typescript-eslint/types": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
+            "integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
+            "dev": true,
+            "engines": {
+                "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            }
+        },
+        "node_modules/@typescript-eslint/typescript-estree": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
+            "integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/visitor-keys": "4.16.1",
+                "debug": "^4.1.1",
+                "globby": "^11.0.1",
+                "is-glob": "^4.0.1",
+                "semver": "^7.3.2",
+                "tsutils": "^3.17.1"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/@typescript-eslint/visitor-keys": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
+            "integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/types": "4.16.1",
+                "eslint-visitor-keys": "^2.0.0"
+            },
+            "engines": {
+                "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            }
+        },
+        "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+            "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/acorn": {
+            "version": "7.4.1",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+            "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+            "dev": true,
+            "bin": {
+                "acorn": "bin/acorn"
+            },
+            "engines": {
+                "node": ">=0.4.0"
+            }
+        },
+        "node_modules/acorn-jsx": {
+            "version": "5.3.1",
+            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
+            "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+            "dev": true,
+            "peerDependencies": {
+                "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+            }
+        },
+        "node_modules/ajv": {
+            "version": "6.12.6",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+            "dev": true,
+            "dependencies": {
+                "fast-deep-equal": "^3.1.1",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.4.1",
+                "uri-js": "^4.2.2"
+            },
+            "funding": {
+                "type": "github",
+                "url": "https://github.com/sponsors/epoberezkin"
+            }
+        },
+        "node_modules/ansi-colors": {
+            "version": "4.1.1",
+            "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+            "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+            "dev": true,
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/ansi-regex": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+            "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/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,
+            "dependencies": {
+                "color-convert": "^1.9.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/argparse": {
+            "version": "1.0.10",
+            "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+            "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+            "dev": true,
+            "dependencies": {
+                "sprintf-js": "~1.0.2"
+            }
+        },
+        "node_modules/array-union": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+            "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/astral-regex": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+            "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/balanced-match": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+            "dev": true
+        },
+        "node_modules/brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "dev": true,
+            "dependencies": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "node_modules/braces": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+            "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+            "dev": true,
+            "dependencies": {
+                "fill-range": "^7.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/callsites": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/chalk": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+            "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+            "dev": true,
+            "dependencies": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/chalk?sponsor=1"
+            }
+        },
+        "node_modules/chalk/node_modules/ansi-styles": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+            "dev": true,
+            "dependencies": {
+                "color-convert": "^2.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/chalk/node_modules/color-convert": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+            "dev": true,
+            "dependencies": {
+                "color-name": "~1.1.4"
+            },
+            "engines": {
+                "node": ">=7.0.0"
+            }
+        },
+        "node_modules/chalk/node_modules/color-name": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+            "dev": true
+        },
+        "node_modules/chalk/node_modules/has-flag": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/chalk/node_modules/supports-color": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+            "dev": true,
+            "dependencies": {
+                "has-flag": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/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==",
+            "dev": true,
+            "dependencies": {
+                "color-name": "1.1.3"
+            }
+        },
+        "node_modules/color-name": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+            "dev": true
+        },
+        "node_modules/concat-map": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+            "dev": true
+        },
+        "node_modules/cross-spawn": {
+            "version": "7.0.3",
+            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+            "dev": true,
+            "dependencies": {
+                "path-key": "^3.1.0",
+                "shebang-command": "^2.0.0",
+                "which": "^2.0.1"
+            },
+            "engines": {
+                "node": ">= 8"
+            }
+        },
+        "node_modules/debug": {
+            "version": "4.1.1",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+            "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+            "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+            "dev": true,
+            "dependencies": {
+                "ms": "^2.1.1"
+            }
+        },
+        "node_modules/deep-is": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+            "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+            "dev": true
+        },
+        "node_modules/dir-glob": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+            "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+            "dev": true,
+            "dependencies": {
+                "path-type": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/doctrine": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+            "dev": true,
+            "dependencies": {
+                "esutils": "^2.0.2"
+            },
+            "engines": {
+                "node": ">=6.0.0"
+            }
+        },
+        "node_modules/emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+            "dev": true
+        },
+        "node_modules/enquirer": {
+            "version": "2.3.6",
+            "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+            "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+            "dev": true,
+            "dependencies": {
+                "ansi-colors": "^4.1.1"
+            },
+            "engines": {
+                "node": ">=8.6"
+            }
+        },
+        "node_modules/escape-string-regexp": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.8.0"
+            }
+        },
+        "node_modules/eslint": {
+            "version": "7.21.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
+            "integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
+            "dev": true,
+            "dependencies": {
+                "@babel/code-frame": "7.12.11",
+                "@eslint/eslintrc": "^0.4.0",
+                "ajv": "^6.10.0",
+                "chalk": "^4.0.0",
+                "cross-spawn": "^7.0.2",
+                "debug": "^4.0.1",
+                "doctrine": "^3.0.0",
+                "enquirer": "^2.3.5",
+                "eslint-scope": "^5.1.1",
+                "eslint-utils": "^2.1.0",
+                "eslint-visitor-keys": "^2.0.0",
+                "espree": "^7.3.1",
+                "esquery": "^1.4.0",
+                "esutils": "^2.0.2",
+                "file-entry-cache": "^6.0.1",
+                "functional-red-black-tree": "^1.0.1",
+                "glob-parent": "^5.0.0",
+                "globals": "^12.1.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.0.0",
+                "imurmurhash": "^0.1.4",
+                "is-glob": "^4.0.0",
+                "js-yaml": "^3.13.1",
+                "json-stable-stringify-without-jsonify": "^1.0.1",
+                "levn": "^0.4.1",
+                "lodash": "^4.17.20",
+                "minimatch": "^3.0.4",
+                "natural-compare": "^1.4.0",
+                "optionator": "^0.9.1",
+                "progress": "^2.0.0",
+                "regexpp": "^3.1.0",
+                "semver": "^7.2.1",
+                "strip-ansi": "^6.0.0",
+                "strip-json-comments": "^3.1.0",
+                "table": "^6.0.4",
+                "text-table": "^0.2.0",
+                "v8-compile-cache": "^2.0.3"
+            },
+            "bin": {
+                "eslint": "bin/eslint.js"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
+        "node_modules/eslint-scope": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
+            "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
+            "dev": true,
+            "dependencies": {
+                "esrecurse": "^4.1.0",
+                "estraverse": "^4.1.1"
+            },
+            "engines": {
+                "node": ">=8.0.0"
+            }
+        },
+        "node_modules/eslint-utils": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+            "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+            "dev": true,
+            "dependencies": {
+                "eslint-visitor-keys": "^1.1.0"
+            },
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/eslint-visitor-keys": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
+            "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/eslint/node_modules/eslint-scope": {
+            "version": "5.1.1",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+            "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+            "dev": true,
+            "dependencies": {
+                "esrecurse": "^4.3.0",
+                "estraverse": "^4.1.1"
+            },
+            "engines": {
+                "node": ">=8.0.0"
+            }
+        },
+        "node_modules/eslint/node_modules/eslint-utils": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+            "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+            "dev": true,
+            "dependencies": {
+                "eslint-visitor-keys": "^1.1.0"
+            },
+            "engines": {
+                "node": ">=6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/mysticatea"
+            }
+        },
+        "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/eslint/node_modules/eslint-visitor-keys": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+            "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/eslint/node_modules/esrecurse": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+            "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+            "dev": true,
+            "dependencies": {
+                "estraverse": "^5.2.0"
+            },
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/eslint/node_modules/esrecurse/node_modules/estraverse": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+            "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/espree": {
+            "version": "7.3.1",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+            "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+            "dev": true,
+            "dependencies": {
+                "acorn": "^7.4.0",
+                "acorn-jsx": "^5.3.1",
+                "eslint-visitor-keys": "^1.3.0"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            }
+        },
+        "node_modules/espree/node_modules/eslint-visitor-keys": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/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,
+            "bin": {
+                "esparse": "bin/esparse.js",
+                "esvalidate": "bin/esvalidate.js"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/esquery": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+            "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+            "dev": true,
+            "dependencies": {
+                "estraverse": "^5.1.0"
+            },
+            "engines": {
+                "node": ">=0.10"
+            }
+        },
+        "node_modules/esquery/node_modules/estraverse": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+            "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/esrecurse": {
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+            "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+            "dev": true,
+            "dependencies": {
+                "estraverse": "^4.1.0"
+            },
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/estraverse": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+            "dev": true,
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/esutils": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/fast-deep-equal": {
+            "version": "3.1.3",
+            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+            "dev": true
+        },
+        "node_modules/fast-glob": {
+            "version": "3.2.5",
+            "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+            "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+            "dev": true,
+            "dependencies": {
+                "@nodelib/fs.stat": "^2.0.2",
+                "@nodelib/fs.walk": "^1.2.3",
+                "glob-parent": "^5.1.0",
+                "merge2": "^1.3.0",
+                "micromatch": "^4.0.2",
+                "picomatch": "^2.2.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/fast-json-stable-stringify": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+            "dev": true
+        },
+        "node_modules/fast-levenshtein": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+            "dev": true
+        },
+        "node_modules/fastq": {
+            "version": "1.11.0",
+            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+            "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+            "dev": true,
+            "dependencies": {
+                "reusify": "^1.0.4"
+            }
+        },
+        "node_modules/file-entry-cache": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+            "dev": true,
+            "dependencies": {
+                "flat-cache": "^3.0.4"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            }
+        },
+        "node_modules/fill-range": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+            "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+            "dev": true,
+            "dependencies": {
+                "to-regex-range": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/flat-cache": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+            "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+            "dev": true,
+            "dependencies": {
+                "flatted": "^3.1.0",
+                "rimraf": "^3.0.2"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            }
+        },
+        "node_modules/flatted": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
+            "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
+            "dev": true
+        },
+        "node_modules/fs.realpath": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+            "dev": true
+        },
+        "node_modules/functional-red-black-tree": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+            "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+            "dev": true
+        },
+        "node_modules/glob": {
+            "version": "7.1.6",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+            "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+            "dev": true,
+            "dependencies": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.0.4",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+            },
+            "engines": {
+                "node": "*"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/glob-parent": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+            "dev": true,
+            "dependencies": {
+                "is-glob": "^4.0.1"
+            },
+            "engines": {
+                "node": ">= 6"
+            }
+        },
+        "node_modules/globals": {
+            "version": "12.4.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+            "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+            "dev": true,
+            "dependencies": {
+                "type-fest": "^0.8.1"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/globby": {
+            "version": "11.0.2",
+            "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
+            "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
+            "dev": true,
+            "dependencies": {
+                "array-union": "^2.1.0",
+                "dir-glob": "^3.0.1",
+                "fast-glob": "^3.1.1",
+                "ignore": "^5.1.4",
+                "merge2": "^1.3.0",
+                "slash": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/globby/node_modules/ignore": {
+            "version": "5.1.8",
+            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+            "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+            "dev": true,
+            "engines": {
+                "node": ">= 4"
+            }
+        },
+        "node_modules/has-flag": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/ignore": {
+            "version": "4.0.6",
+            "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+            "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+            "dev": true,
+            "engines": {
+                "node": ">= 4"
+            }
+        },
+        "node_modules/import-fresh": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+            "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+            "dev": true,
+            "dependencies": {
+                "parent-module": "^1.0.0",
+                "resolve-from": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/imurmurhash": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.8.19"
+            }
+        },
+        "node_modules/inflight": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+            "dev": true,
+            "dependencies": {
+                "once": "^1.3.0",
+                "wrappy": "1"
+            }
+        },
+        "node_modules/inherits": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+            "dev": true
+        },
+        "node_modules/is-extglob": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/is-fullwidth-code-point": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+            "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/is-glob": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+            "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+            "dev": true,
+            "dependencies": {
+                "is-extglob": "^2.1.1"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/is-number": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+            "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.12.0"
+            }
+        },
+        "node_modules/isexe": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+            "dev": true
+        },
+        "node_modules/js-tokens": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+            "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+            "dev": true
+        },
+        "node_modules/js-yaml": {
+            "version": "3.14.1",
+            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+            "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+            "dev": true,
+            "dependencies": {
+                "argparse": "^1.0.7",
+                "esprima": "^4.0.0"
+            },
+            "bin": {
+                "js-yaml": "bin/js-yaml.js"
+            }
+        },
+        "node_modules/json-schema-traverse": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+            "dev": true
+        },
+        "node_modules/json-stable-stringify-without-jsonify": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+            "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+            "dev": true
+        },
+        "node_modules/levn": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+            "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+            "dev": true,
+            "dependencies": {
+                "prelude-ls": "^1.2.1",
+                "type-check": "~0.4.0"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
+        "node_modules/lodash": {
+            "version": "4.17.21",
+            "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+            "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+            "dev": true
+        },
+        "node_modules/lru-cache": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+            "dev": true,
+            "dependencies": {
+                "yallist": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/merge2": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+            "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+            "dev": true,
+            "engines": {
+                "node": ">= 8"
+            }
+        },
+        "node_modules/micromatch": {
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+            "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+            "dev": true,
+            "dependencies": {
+                "braces": "^3.0.1",
+                "picomatch": "^2.0.5"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/minimatch": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+            "dev": true,
+            "dependencies": {
+                "brace-expansion": "^1.1.7"
+            },
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/ms": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+            "dev": true
+        },
+        "node_modules/natural-compare": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+            "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+            "dev": true
+        },
+        "node_modules/once": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "dev": true,
+            "dependencies": {
+                "wrappy": "1"
+            }
+        },
+        "node_modules/optionator": {
+            "version": "0.9.1",
+            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+            "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+            "dev": true,
+            "dependencies": {
+                "deep-is": "^0.1.3",
+                "fast-levenshtein": "^2.0.6",
+                "levn": "^0.4.1",
+                "prelude-ls": "^1.2.1",
+                "type-check": "^0.4.0",
+                "word-wrap": "^1.2.3"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
+        "node_modules/parent-module": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+            "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+            "dev": true,
+            "dependencies": {
+                "callsites": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/path-is-absolute": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/path-key": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+            "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/path-type": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+            "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/picomatch": {
+            "version": "2.2.2",
+            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+            "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+            "dev": true,
+            "engines": {
+                "node": ">=8.6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/jonschlinkert"
+            }
+        },
+        "node_modules/prelude-ls": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+            "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+            "dev": true,
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
+        "node_modules/progress": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+            "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.4.0"
+            }
+        },
+        "node_modules/punycode": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+            "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+            "dev": true,
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/queue-microtask": {
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz",
+            "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==",
+            "dev": true,
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ]
+        },
+        "node_modules/regexpp": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+            "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/mysticatea"
+            }
+        },
+        "node_modules/require-from-string": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+            "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/resolve-from": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+            "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/reusify": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+            "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+            "dev": true,
+            "engines": {
+                "iojs": ">=1.0.0",
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/rimraf": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+            "dev": true,
+            "dependencies": {
+                "glob": "^7.1.3"
+            },
+            "bin": {
+                "rimraf": "bin.js"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/run-parallel": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+            "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+            "dev": true,
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "dependencies": {
+                "queue-microtask": "^1.2.2"
+            }
+        },
+        "node_modules/semver": {
+            "version": "7.3.4",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+            "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+            "dev": true,
+            "dependencies": {
+                "lru-cache": "^6.0.0"
+            },
+            "bin": {
+                "semver": "bin/semver.js"
+            },
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/shebang-command": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+            "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+            "dev": true,
+            "dependencies": {
+                "shebang-regex": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/shebang-regex": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+            "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/slash": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+            "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/slice-ansi": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+            "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+            "dev": true,
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "astral-regex": "^2.0.0",
+                "is-fullwidth-code-point": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+            }
+        },
+        "node_modules/slice-ansi/node_modules/ansi-styles": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+            "dev": true,
+            "dependencies": {
+                "color-convert": "^2.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/slice-ansi/node_modules/color-convert": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+            "dev": true,
+            "dependencies": {
+                "color-name": "~1.1.4"
+            },
+            "engines": {
+                "node": ">=7.0.0"
+            }
+        },
+        "node_modules/slice-ansi/node_modules/color-name": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+            "dev": true
+        },
+        "node_modules/sprintf-js": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+            "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+            "dev": true
+        },
+        "node_modules/string-width": {
+            "version": "4.2.2",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+            "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+            "dev": true,
+            "dependencies": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/strip-ansi": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+            "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+            "dev": true,
+            "dependencies": {
+                "ansi-regex": "^5.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/strip-json-comments": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/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,
+            "dependencies": {
+                "has-flag": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/table": {
+            "version": "6.0.7",
+            "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
+            "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
+            "dev": true,
+            "dependencies": {
+                "ajv": "^7.0.2",
+                "lodash": "^4.17.20",
+                "slice-ansi": "^4.0.0",
+                "string-width": "^4.2.0"
+            },
+            "engines": {
+                "node": ">=10.0.0"
+            }
+        },
+        "node_modules/table/node_modules/ajv": {
+            "version": "7.1.1",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz",
+            "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==",
+            "dev": true,
+            "dependencies": {
+                "fast-deep-equal": "^3.1.1",
+                "json-schema-traverse": "^1.0.0",
+                "require-from-string": "^2.0.2",
+                "uri-js": "^4.2.2"
+            },
+            "funding": {
+                "type": "github",
+                "url": "https://github.com/sponsors/epoberezkin"
+            }
+        },
+        "node_modules/table/node_modules/json-schema-traverse": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+            "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+            "dev": true
+        },
+        "node_modules/text-table": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+            "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+            "dev": true
+        },
+        "node_modules/to-regex-range": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+            "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+            "dev": true,
+            "dependencies": {
+                "is-number": "^7.0.0"
+            },
+            "engines": {
+                "node": ">=8.0"
+            }
+        },
+        "node_modules/tslib": {
+            "version": "1.11.1",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+            "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==",
+            "dev": true
+        },
+        "node_modules/tsutils": {
+            "version": "3.20.0",
+            "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.20.0.tgz",
+            "integrity": "sha512-RYbuQuvkhuqVeXweWT3tJLKOEJ/UUw9GjNEZGWdrLLlM+611o1gwLHBpxoFJKKl25fLprp2eVthtKs5JOrNeXg==",
+            "dev": true,
+            "dependencies": {
+                "tslib": "^1.8.1"
+            },
+            "engines": {
+                "node": ">= 6"
+            },
+            "peerDependencies": {
+                "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+            }
+        },
+        "node_modules/type-check": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+            "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+            "dev": true,
+            "dependencies": {
+                "prelude-ls": "^1.2.1"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
+        "node_modules/type-fest": {
+            "version": "0.8.1",
+            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+            "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/typescript": {
+            "version": "4.3.5",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
+            "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
+            "dev": true,
+            "bin": {
+                "tsc": "bin/tsc",
+                "tsserver": "bin/tsserver"
+            },
+            "engines": {
+                "node": ">=4.2.0"
+            }
+        },
+        "node_modules/uri-js": {
+            "version": "4.4.1",
+            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+            "dev": true,
+            "dependencies": {
+                "punycode": "^2.1.0"
+            }
+        },
+        "node_modules/v8-compile-cache": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz",
+            "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==",
+            "dev": true
+        },
+        "node_modules/which": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+            "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+            "dev": true,
+            "dependencies": {
+                "isexe": "^2.0.0"
+            },
+            "bin": {
+                "node-which": "bin/node-which"
+            },
+            "engines": {
+                "node": ">= 8"
+            }
+        },
+        "node_modules/word-wrap": {
+            "version": "1.2.3",
+            "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+            "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/wrappy": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+            "dev": true
+        },
+        "node_modules/yallist": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+            "dev": true
+        }
+    },
+    "dependencies": {
+        "@babel/code-frame": {
+            "version": "7.12.11",
+            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+            "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+            "dev": true,
+            "requires": {
+                "@babel/highlight": "^7.10.4"
+            }
+        },
+        "@babel/helper-validator-identifier": {
+            "version": "7.12.11",
+            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
+            "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
+            "dev": true
+        },
+        "@babel/highlight": {
+            "version": "7.13.8",
+            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.8.tgz",
+            "integrity": "sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-validator-identifier": "^7.12.11",
+                "chalk": "^2.0.0",
+                "js-tokens": "^4.0.0"
+            },
+            "dependencies": {
+                "chalk": {
+                    "version": "2.4.2",
+                    "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+                    "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-styles": "^3.2.1",
+                        "escape-string-regexp": "^1.0.5",
+                        "supports-color": "^5.3.0"
+                    }
+                }
+            }
+        },
+        "@eslint/eslintrc": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
+            "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
+            "dev": true,
+            "requires": {
+                "ajv": "^6.12.4",
+                "debug": "^4.1.1",
+                "espree": "^7.3.0",
+                "globals": "^12.1.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.2.1",
+                "js-yaml": "^3.13.1",
+                "minimatch": "^3.0.4",
+                "strip-json-comments": "^3.1.1"
+            }
+        },
+        "@nodelib/fs.scandir": {
+            "version": "2.1.4",
+            "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+            "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
+            "dev": true,
+            "requires": {
+                "@nodelib/fs.stat": "2.0.4",
+                "run-parallel": "^1.1.9"
+            }
+        },
+        "@nodelib/fs.stat": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+            "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+            "dev": true
+        },
+        "@nodelib/fs.walk": {
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+            "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
+            "dev": true,
+            "requires": {
+                "@nodelib/fs.scandir": "2.1.4",
+                "fastq": "^1.6.0"
+            }
+        },
+        "@types/json-schema": {
+            "version": "7.0.7",
+            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+            "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+            "dev": true
+        },
+        "@types/node": {
+            "version": "12.12.35",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.35.tgz",
+            "integrity": "sha512-ASYsaKecA7TUsDrqIGPNk3JeEox0z/0XR/WsJJ8BIX/9+SkMSImQXKWfU/yBrSyc7ZSE/NPqLu36Nur0miCFfQ==",
+            "dev": true
+        },
+        "@types/vscode": {
+            "version": "1.33.0",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.33.0.tgz",
+            "integrity": "sha512-JSmGiValbrcG5g20jjCfKakLiuWyrcjVezj+SEAEZ4klXQktE5EtowuGlkLVqbkiBK4iY5wy/4yW8OjecuHnjQ==",
+            "dev": true
+        },
+        "@typescript-eslint/eslint-plugin": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.16.1.tgz",
+            "integrity": "sha512-SK777klBdlkUZpZLC1mPvyOWk9yAFCWmug13eAjVQ4/Q1LATE/NbcQL1xDHkptQkZOLnPmLUA1Y54m8dqYwnoQ==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/experimental-utils": "4.16.1",
+                "@typescript-eslint/scope-manager": "4.16.1",
+                "debug": "^4.1.1",
+                "functional-red-black-tree": "^1.0.1",
+                "lodash": "^4.17.15",
+                "regexpp": "^3.0.0",
+                "semver": "^7.3.2",
+                "tsutils": "^3.17.1"
+            }
+        },
+        "@typescript-eslint/experimental-utils": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.16.1.tgz",
+            "integrity": "sha512-0Hm3LSlMYFK17jO4iY3un1Ve9x1zLNn4EM50Lia+0EV99NdbK+cn0er7HC7IvBA23mBg3P+8dUkMXy4leL33UQ==",
+            "dev": true,
+            "requires": {
+                "@types/json-schema": "^7.0.3",
+                "@typescript-eslint/scope-manager": "4.16.1",
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/typescript-estree": "4.16.1",
+                "eslint-scope": "^5.0.0",
+                "eslint-utils": "^2.0.0"
+            }
+        },
+        "@typescript-eslint/parser": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.16.1.tgz",
+            "integrity": "sha512-/c0LEZcDL5y8RyI1zLcmZMvJrsR6SM1uetskFkoh3dvqDKVXPsXI+wFB/CbVw7WkEyyTKobC1mUNp/5y6gRvXg==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/scope-manager": "4.16.1",
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/typescript-estree": "4.16.1",
+                "debug": "^4.1.1"
+            }
+        },
+        "@typescript-eslint/scope-manager": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
+            "integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/visitor-keys": "4.16.1"
+            }
+        },
+        "@typescript-eslint/types": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
+            "integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
+            "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
+            "integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/types": "4.16.1",
+                "@typescript-eslint/visitor-keys": "4.16.1",
+                "debug": "^4.1.1",
+                "globby": "^11.0.1",
+                "is-glob": "^4.0.1",
+                "semver": "^7.3.2",
+                "tsutils": "^3.17.1"
+            }
+        },
+        "@typescript-eslint/visitor-keys": {
+            "version": "4.16.1",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
+            "integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/types": "4.16.1",
+                "eslint-visitor-keys": "^2.0.0"
+            },
+            "dependencies": {
+                "eslint-visitor-keys": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+                    "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+                    "dev": true
+                }
+            }
+        },
+        "acorn": {
+            "version": "7.4.1",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+            "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+            "dev": true
+        },
+        "acorn-jsx": {
+            "version": "5.3.1",
+            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
+            "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+            "dev": true,
+            "requires": {}
+        },
+        "ajv": {
+            "version": "6.12.6",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+            "dev": true,
+            "requires": {
+                "fast-deep-equal": "^3.1.1",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.4.1",
+                "uri-js": "^4.2.2"
+            }
+        },
+        "ansi-colors": {
+            "version": "4.1.1",
+            "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+            "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+            "dev": true
+        },
+        "ansi-regex": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+            "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+            "dev": true
+        },
+        "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.0"
+            }
+        },
+        "argparse": {
+            "version": "1.0.10",
+            "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+            "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+            "dev": true,
+            "requires": {
+                "sprintf-js": "~1.0.2"
+            }
+        },
+        "array-union": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+            "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+            "dev": true
+        },
+        "astral-regex": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+            "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+            "dev": true
+        },
+        "balanced-match": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+            "dev": true
+        },
+        "brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "dev": true,
+            "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "braces": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+            "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+            "dev": true,
+            "requires": {
+                "fill-range": "^7.0.1"
+            }
+        },
+        "callsites": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+            "dev": true
+        },
+        "chalk": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+            "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+            "dev": true,
+            "requires": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+            },
+            "dependencies": {
+                "ansi-styles": {
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+                    "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+                    "dev": true,
+                    "requires": {
+                        "color-convert": "^2.0.1"
+                    }
+                },
+                "color-convert": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+                    "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+                    "dev": true,
+                    "requires": {
+                        "color-name": "~1.1.4"
+                    }
+                },
+                "color-name": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+                    "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+                    "dev": true
+                },
+                "has-flag": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+                    "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+                    "dev": true
+                },
+                "supports-color": {
+                    "version": "7.2.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+                    "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+                    "dev": true,
+                    "requires": {
+                        "has-flag": "^4.0.0"
+                    }
+                }
+            }
+        },
+        "color-convert": {
+            "version": "1.9.3",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+            "dev": true,
+            "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=",
+            "dev": true
+        },
+        "concat-map": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+            "dev": true
+        },
+        "cross-spawn": {
+            "version": "7.0.3",
+            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+            "dev": true,
+            "requires": {
+                "path-key": "^3.1.0",
+                "shebang-command": "^2.0.0",
+                "which": "^2.0.1"
+            }
+        },
+        "debug": {
+            "version": "4.1.1",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+            "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+            "dev": true,
+            "requires": {
+                "ms": "^2.1.1"
+            }
+        },
+        "deep-is": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+            "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+            "dev": true
+        },
+        "dir-glob": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+            "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+            "dev": true,
+            "requires": {
+                "path-type": "^4.0.0"
+            }
+        },
+        "doctrine": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+            "dev": true,
+            "requires": {
+                "esutils": "^2.0.2"
+            }
+        },
+        "emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+            "dev": true
+        },
+        "enquirer": {
+            "version": "2.3.6",
+            "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+            "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+            "dev": true,
+            "requires": {
+                "ansi-colors": "^4.1.1"
+            }
+        },
+        "escape-string-regexp": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+            "dev": true
+        },
+        "eslint": {
+            "version": "7.21.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
+            "integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "7.12.11",
+                "@eslint/eslintrc": "^0.4.0",
+                "ajv": "^6.10.0",
+                "chalk": "^4.0.0",
+                "cross-spawn": "^7.0.2",
+                "debug": "^4.0.1",
+                "doctrine": "^3.0.0",
+                "enquirer": "^2.3.5",
+                "eslint-scope": "^5.1.1",
+                "eslint-utils": "^2.1.0",
+                "eslint-visitor-keys": "^2.0.0",
+                "espree": "^7.3.1",
+                "esquery": "^1.4.0",
+                "esutils": "^2.0.2",
+                "file-entry-cache": "^6.0.1",
+                "functional-red-black-tree": "^1.0.1",
+                "glob-parent": "^5.0.0",
+                "globals": "^12.1.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.0.0",
+                "imurmurhash": "^0.1.4",
+                "is-glob": "^4.0.0",
+                "js-yaml": "^3.13.1",
+                "json-stable-stringify-without-jsonify": "^1.0.1",
+                "levn": "^0.4.1",
+                "lodash": "^4.17.20",
+                "minimatch": "^3.0.4",
+                "natural-compare": "^1.4.0",
+                "optionator": "^0.9.1",
+                "progress": "^2.0.0",
+                "regexpp": "^3.1.0",
+                "semver": "^7.2.1",
+                "strip-ansi": "^6.0.0",
+                "strip-json-comments": "^3.1.0",
+                "table": "^6.0.4",
+                "text-table": "^0.2.0",
+                "v8-compile-cache": "^2.0.3"
+            },
+            "dependencies": {
+                "eslint-scope": {
+                    "version": "5.1.1",
+                    "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+                    "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+                    "dev": true,
+                    "requires": {
+                        "esrecurse": "^4.3.0",
+                        "estraverse": "^4.1.1"
+                    }
+                },
+                "eslint-utils": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+                    "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+                    "dev": true,
+                    "requires": {
+                        "eslint-visitor-keys": "^1.1.0"
+                    },
+                    "dependencies": {
+                        "eslint-visitor-keys": {
+                            "version": "1.3.0",
+                            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+                            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+                            "dev": true
+                        }
+                    }
+                },
+                "eslint-visitor-keys": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+                    "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+                    "dev": true
+                },
+                "esrecurse": {
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+                    "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+                    "dev": true,
+                    "requires": {
+                        "estraverse": "^5.2.0"
+                    },
+                    "dependencies": {
+                        "estraverse": {
+                            "version": "5.2.0",
+                            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+                            "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+                            "dev": true
+                        }
+                    }
+                }
+            }
+        },
+        "eslint-scope": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
+            "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
+            "dev": true,
+            "requires": {
+                "esrecurse": "^4.1.0",
+                "estraverse": "^4.1.1"
+            }
+        },
+        "eslint-utils": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+            "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+            "dev": true,
+            "requires": {
+                "eslint-visitor-keys": "^1.1.0"
+            }
+        },
+        "eslint-visitor-keys": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
+            "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
+            "dev": true
+        },
+        "espree": {
+            "version": "7.3.1",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+            "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+            "dev": true,
+            "requires": {
+                "acorn": "^7.4.0",
+                "acorn-jsx": "^5.3.1",
+                "eslint-visitor-keys": "^1.3.0"
+            },
+            "dependencies": {
+                "eslint-visitor-keys": {
+                    "version": "1.3.0",
+                    "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+                    "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+                    "dev": true
+                }
+            }
+        },
+        "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
+        },
+        "esquery": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+            "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+            "dev": true,
+            "requires": {
+                "estraverse": "^5.1.0"
+            },
+            "dependencies": {
+                "estraverse": {
+                    "version": "5.2.0",
+                    "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+                    "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+                    "dev": true
+                }
+            }
+        },
+        "esrecurse": {
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+            "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+            "dev": true,
+            "requires": {
+                "estraverse": "^4.1.0"
+            }
+        },
+        "estraverse": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+            "dev": true
+        },
+        "esutils": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+            "dev": true
+        },
+        "fast-deep-equal": {
+            "version": "3.1.3",
+            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+            "dev": true
+        },
+        "fast-glob": {
+            "version": "3.2.5",
+            "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+            "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+            "dev": true,
+            "requires": {
+                "@nodelib/fs.stat": "^2.0.2",
+                "@nodelib/fs.walk": "^1.2.3",
+                "glob-parent": "^5.1.0",
+                "merge2": "^1.3.0",
+                "micromatch": "^4.0.2",
+                "picomatch": "^2.2.1"
+            }
+        },
+        "fast-json-stable-stringify": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+            "dev": true
+        },
+        "fast-levenshtein": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+            "dev": true
+        },
+        "fastq": {
+            "version": "1.11.0",
+            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+            "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+            "dev": true,
+            "requires": {
+                "reusify": "^1.0.4"
+            }
+        },
+        "file-entry-cache": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+            "dev": true,
+            "requires": {
+                "flat-cache": "^3.0.4"
+            }
+        },
+        "fill-range": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+            "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+            "dev": true,
+            "requires": {
+                "to-regex-range": "^5.0.1"
+            }
+        },
+        "flat-cache": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+            "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+            "dev": true,
+            "requires": {
+                "flatted": "^3.1.0",
+                "rimraf": "^3.0.2"
+            }
+        },
+        "flatted": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
+            "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
+            "dev": true
+        },
+        "fs.realpath": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+            "dev": true
+        },
+        "functional-red-black-tree": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+            "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+            "dev": true
+        },
+        "glob": {
+            "version": "7.1.6",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+            "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+            "dev": true,
+            "requires": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.0.4",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+            }
+        },
+        "glob-parent": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+            "dev": true,
+            "requires": {
+                "is-glob": "^4.0.1"
+            }
+        },
+        "globals": {
+            "version": "12.4.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+            "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+            "dev": true,
+            "requires": {
+                "type-fest": "^0.8.1"
+            }
+        },
+        "globby": {
+            "version": "11.0.2",
+            "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
+            "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
+            "dev": true,
+            "requires": {
+                "array-union": "^2.1.0",
+                "dir-glob": "^3.0.1",
+                "fast-glob": "^3.1.1",
+                "ignore": "^5.1.4",
+                "merge2": "^1.3.0",
+                "slash": "^3.0.0"
+            },
+            "dependencies": {
+                "ignore": {
+                    "version": "5.1.8",
+                    "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+                    "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+                    "dev": true
+                }
+            }
+        },
+        "has-flag": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+            "dev": true
+        },
+        "ignore": {
+            "version": "4.0.6",
+            "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+            "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+            "dev": true
+        },
+        "import-fresh": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+            "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+            "dev": true,
+            "requires": {
+                "parent-module": "^1.0.0",
+                "resolve-from": "^4.0.0"
+            }
+        },
+        "imurmurhash": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+            "dev": true
+        },
+        "inflight": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+            "dev": true,
+            "requires": {
+                "once": "^1.3.0",
+                "wrappy": "1"
+            }
+        },
+        "inherits": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+            "dev": true
+        },
+        "is-extglob": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+            "dev": true
+        },
+        "is-fullwidth-code-point": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+            "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+            "dev": true
+        },
+        "is-glob": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+            "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+            "dev": true,
+            "requires": {
+                "is-extglob": "^2.1.1"
+            }
+        },
+        "is-number": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+            "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+            "dev": true
+        },
+        "isexe": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+            "dev": true
+        },
+        "js-tokens": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+            "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+            "dev": true
+        },
+        "js-yaml": {
+            "version": "3.14.1",
+            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+            "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+            "dev": true,
+            "requires": {
+                "argparse": "^1.0.7",
+                "esprima": "^4.0.0"
+            }
+        },
+        "json-schema-traverse": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+            "dev": true
+        },
+        "json-stable-stringify-without-jsonify": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+            "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+            "dev": true
+        },
+        "levn": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+            "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+            "dev": true,
+            "requires": {
+                "prelude-ls": "^1.2.1",
+                "type-check": "~0.4.0"
+            }
+        },
+        "lodash": {
+            "version": "4.17.21",
+            "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+            "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+            "dev": true
+        },
+        "lru-cache": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+            "dev": true,
+            "requires": {
+                "yallist": "^4.0.0"
+            }
+        },
+        "merge2": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+            "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+            "dev": true
+        },
+        "micromatch": {
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+            "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+            "dev": true,
+            "requires": {
+                "braces": "^3.0.1",
+                "picomatch": "^2.0.5"
+            }
+        },
+        "minimatch": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+            "dev": true,
+            "requires": {
+                "brace-expansion": "^1.1.7"
+            }
+        },
+        "ms": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+            "dev": true
+        },
+        "natural-compare": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+            "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+            "dev": true
+        },
+        "once": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "dev": true,
+            "requires": {
+                "wrappy": "1"
+            }
+        },
+        "optionator": {
+            "version": "0.9.1",
+            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+            "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+            "dev": true,
+            "requires": {
+                "deep-is": "^0.1.3",
+                "fast-levenshtein": "^2.0.6",
+                "levn": "^0.4.1",
+                "prelude-ls": "^1.2.1",
+                "type-check": "^0.4.0",
+                "word-wrap": "^1.2.3"
+            }
+        },
+        "parent-module": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+            "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+            "dev": true,
+            "requires": {
+                "callsites": "^3.0.0"
+            }
+        },
+        "path-is-absolute": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+            "dev": true
+        },
+        "path-key": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+            "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+            "dev": true
+        },
+        "path-type": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+            "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+            "dev": true
+        },
+        "picomatch": {
+            "version": "2.2.2",
+            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+            "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+            "dev": true
+        },
+        "prelude-ls": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+            "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+            "dev": true
+        },
+        "progress": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+            "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+            "dev": true
+        },
+        "punycode": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+            "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+            "dev": true
+        },
+        "queue-microtask": {
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz",
+            "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==",
+            "dev": true
+        },
+        "regexpp": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+            "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+            "dev": true
+        },
+        "require-from-string": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+            "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+            "dev": true
+        },
+        "resolve-from": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+            "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+            "dev": true
+        },
+        "reusify": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+            "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+            "dev": true
+        },
+        "rimraf": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+            "dev": true,
+            "requires": {
+                "glob": "^7.1.3"
+            }
+        },
+        "run-parallel": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+            "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+            "dev": true,
+            "requires": {
+                "queue-microtask": "^1.2.2"
+            }
+        },
+        "semver": {
+            "version": "7.3.4",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+            "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+            "dev": true,
+            "requires": {
+                "lru-cache": "^6.0.0"
+            }
+        },
+        "shebang-command": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+            "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+            "dev": true,
+            "requires": {
+                "shebang-regex": "^3.0.0"
+            }
+        },
+        "shebang-regex": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+            "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+            "dev": true
+        },
+        "slash": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+            "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+            "dev": true
+        },
+        "slice-ansi": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+            "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+            "dev": true,
+            "requires": {
+                "ansi-styles": "^4.0.0",
+                "astral-regex": "^2.0.0",
+                "is-fullwidth-code-point": "^3.0.0"
+            },
+            "dependencies": {
+                "ansi-styles": {
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+                    "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+                    "dev": true,
+                    "requires": {
+                        "color-convert": "^2.0.1"
+                    }
+                },
+                "color-convert": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+                    "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+                    "dev": true,
+                    "requires": {
+                        "color-name": "~1.1.4"
+                    }
+                },
+                "color-name": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+                    "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+                    "dev": true
+                }
+            }
+        },
+        "sprintf-js": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+            "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+            "dev": true
+        },
+        "string-width": {
+            "version": "4.2.2",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+            "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+            "dev": true,
+            "requires": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.0"
+            }
+        },
+        "strip-ansi": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+            "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+            "dev": true,
+            "requires": {
+                "ansi-regex": "^5.0.0"
+            }
+        },
+        "strip-json-comments": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+            "dev": true
+        },
+        "supports-color": {
+            "version": "5.5.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+            "dev": true,
+            "requires": {
+                "has-flag": "^3.0.0"
+            }
+        },
+        "table": {
+            "version": "6.0.7",
+            "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
+            "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
+            "dev": true,
+            "requires": {
+                "ajv": "^7.0.2",
+                "lodash": "^4.17.20",
+                "slice-ansi": "^4.0.0",
+                "string-width": "^4.2.0"
+            },
+            "dependencies": {
+                "ajv": {
+                    "version": "7.1.1",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz",
+                    "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==",
+                    "dev": true,
+                    "requires": {
+                        "fast-deep-equal": "^3.1.1",
+                        "json-schema-traverse": "^1.0.0",
+                        "require-from-string": "^2.0.2",
+                        "uri-js": "^4.2.2"
+                    }
+                },
+                "json-schema-traverse": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+                    "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+                    "dev": true
+                }
+            }
+        },
+        "text-table": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+            "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+            "dev": true
+        },
+        "to-regex-range": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+            "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+            "dev": true,
+            "requires": {
+                "is-number": "^7.0.0"
+            }
+        },
+        "tslib": {
+            "version": "1.11.1",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+            "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==",
+            "dev": true
+        },
+        "tsutils": {
+            "version": "3.20.0",
+            "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.20.0.tgz",
+            "integrity": "sha512-RYbuQuvkhuqVeXweWT3tJLKOEJ/UUw9GjNEZGWdrLLlM+611o1gwLHBpxoFJKKl25fLprp2eVthtKs5JOrNeXg==",
+            "dev": true,
+            "requires": {
+                "tslib": "^1.8.1"
+            }
+        },
+        "type-check": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+            "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+            "dev": true,
+            "requires": {
+                "prelude-ls": "^1.2.1"
+            }
+        },
+        "type-fest": {
+            "version": "0.8.1",
+            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+            "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+            "dev": true
+        },
+        "typescript": {
+            "version": "4.3.5",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
+            "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
+            "dev": true
+        },
+        "uri-js": {
+            "version": "4.4.1",
+            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+            "dev": true,
+            "requires": {
+                "punycode": "^2.1.0"
+            }
+        },
+        "v8-compile-cache": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz",
+            "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==",
+            "dev": true
+        },
+        "which": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+            "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+            "dev": true,
+            "requires": {
+                "isexe": "^2.0.0"
+            }
+        },
+        "word-wrap": {
+            "version": "1.2.3",
+            "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+            "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+            "dev": true
+        },
+        "wrappy": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+            "dev": true
+        },
+        "yallist": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+            "dev": true
+        }
+    }
+}

+ 50 - 0
extension/package.json

@@ -0,0 +1,50 @@
+{
+    "name": "dioxusstudio",
+    "displayName": "dioxusStudio",
+    "description": "Toolkit for IDE support in Dioxus apps",
+    "version": "0.0.1",
+    "publisher": "jkelleyrtp",
+    "private": true,
+    "license": "MIT",
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/Microsoft/vscode-extension-samples"
+    },
+    "engines": {
+        "vscode": "^1.32.0"
+    },
+    "categories": [
+        "Other"
+    ],
+    "activationEvents": [
+        "onCommand:extension.htmlToRsx",
+        "onCommand:extension.htmlToComponent"
+    ],
+    "main": "./out/extension",
+    "contributes": {
+        "commands": [
+            {
+                "command": "extension.htmlToRsx",
+                "title": "Convert HTML to RSX"
+            },
+            {
+                "command": "extension.htmlToComponent",
+                "title": "Convert HTML to Dioxus Component"
+            }
+        ]
+    },
+    "scripts": {
+        "vscode:prepublish": "npm run compile",
+        "compile": "tsc -p ./",
+        "lint": "eslint . --ext .ts,.tsx",
+        "watch": "tsc -watch -p ./"
+    },
+    "devDependencies": {
+        "@types/node": "^12.12.0",
+        "@types/vscode": "^1.32.0",
+        "@typescript-eslint/eslint-plugin": "^4.16.0",
+        "@typescript-eslint/parser": "^4.16.0",
+        "eslint": "^7.21.0",
+        "typescript": "^4.3.5"
+    }
+}

+ 57 - 0
extension/src/extension.ts

@@ -0,0 +1,57 @@
+'use strict';
+
+import * as vscode from 'vscode';
+import { spawn } from "child_process";
+
+export function activate(context: vscode.ExtensionContext) {
+	const htmlToPureRsx = vscode.commands.registerCommand('extension.htmlToRsx', function () {
+		// Get the active text editor
+		const editor = vscode.window.activeTextEditor;
+
+		if (editor) {
+			const document = editor.document;
+			const selection = editor.selection;
+			const word = document.getText(selection);
+
+			const child_proc = spawn("dioxus", ["translate", "-t", word]);
+
+			let result = '';
+			child_proc.stdout?.on('data', data => result += data);
+
+			child_proc.on('close', () => {
+				editor.edit(editBuilder => {
+					if (result != '') {
+						editBuilder.replace(selection, result)
+					}
+				})
+			});
+		}
+	});
+
+	const htmlToComponent = vscode.commands.registerCommand('extension.htmlToComponent', function () {
+		// Get the active text editor
+		const editor = vscode.window.activeTextEditor;
+
+		if (editor) {
+			const document = editor.document;
+			const selection = editor.selection;
+			const word = document.getText(selection);
+
+			const child_proc = spawn("dioxus", ["translate", "-c", "-t", word]);
+
+			let result = '';
+			child_proc.stdout?.on('data', data => result += data);
+
+			child_proc.on('close', () => {
+				editor.edit(editBuilder => {
+					if (result != '') {
+						editBuilder.replace(selection, result)
+					}
+				})
+			});
+		}
+	});
+
+	context.subscriptions.push(htmlToPureRsx);
+	context.subscriptions.push(htmlToComponent);
+}

+ 12 - 0
extension/tsconfig.json

@@ -0,0 +1,12 @@
+{
+	"compilerOptions": {
+		"module": "commonjs",
+		"target": "es2019",
+		"lib": ["ES2019"],
+		"outDir": "out",
+		"sourceMap": true,
+		"strict": true,
+		"rootDir": "src"
+	},
+	"exclude": ["node_modules", ".vscode-test"]
+}

+ 55 - 26
src/builder.rs

@@ -1,25 +1,15 @@
 use crate::{
     cli::BuildOptions,
-    config::{Config, ExecutableType},
-    error::Result,
+    config::{CrateConfig, ExecutableType},
+    error::{Error, Result},
+};
+use std::{
+    io::{Read, Write},
+    process::Command,
 };
-use log::{info, warn};
-use std::{io::Write, process::Command};
 use wasm_bindgen_cli_support::Bindgen;
 
-pub struct BuildConfig {}
-impl Into<BuildConfig> for BuildOptions {
-    fn into(self) -> BuildConfig {
-        BuildConfig {}
-    }
-}
-impl Default for BuildConfig {
-    fn default() -> Self {
-        Self {}
-    }
-}
-
-pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
+pub fn build(config: &CrateConfig) -> Result<()> {
     /*
     [1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
     [2] Generate the appropriate build folders
@@ -28,7 +18,7 @@ pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
     [5] Link up the html page to the wasm module
     */
 
-    let Config {
+    let CrateConfig {
         out_dir,
         crate_dir,
         target_dir,
@@ -40,7 +30,7 @@ pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
     let t_start = std::time::Instant::now();
 
     // [1] Build the .wasm module
-    info!("Running build commands...");
+    log::info!("Running build commands...");
     let mut cmd = Command::new("cargo");
     cmd.current_dir(&crate_dir)
         .arg("build")
@@ -60,9 +50,16 @@ pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
     };
 
     let mut child = cmd.spawn()?;
-    let _err_code = child.wait()?;
-
-    info!("Build complete!");
+    let output = child.wait()?;
+
+    if output.success() {
+        log::info!("Build complete!");
+    } else {
+        log::error!("Build failed!");
+        let mut reason = String::new();
+        child.stderr.unwrap().read_to_string(&mut reason)?;
+        return Err(Error::BuildFailed(reason));
+    }
 
     // [2] Establish the output directory structure
     let bindgen_outdir = out_dir.join("wasm");
@@ -77,12 +74,10 @@ pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
 
     let input_path = match executable {
         ExecutableType::Binary(name) | ExecutableType::Lib(name) => target_dir
-            // .join("wasm32-unknown-unknown/release")
             .join(format!("wasm32-unknown-unknown/{}", release_type))
             .join(format!("{}.wasm", name)),
 
         ExecutableType::Example(name) => target_dir
-            // .join("wasm32-unknown-unknown/release/examples")
             .join(format!("wasm32-unknown-unknown/{}/examples", release_type))
             .join(format!("{}.wasm", name)),
     };
@@ -103,7 +98,7 @@ pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
 
     // [5] Generate the html file with the module name
     // TODO: support names via options
-    info!("Writing to '{:#?}' directory...", out_dir);
+    log::info!("Writing to '{:#?}' directory...", out_dir);
     let mut file = std::fs::File::create(out_dir.join("index.html"))?;
     file.write_all(gen_page("./wasm/module.js").as_str().as_bytes())?;
 
@@ -111,7 +106,7 @@ pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
     match fs_extra::dir::copy(static_dir, out_dir, &copy_options) {
         Ok(_) => {}
         Err(_e) => {
-            warn!("Error copying dir");
+            log::warn!("Error copying dir");
         }
     }
 
@@ -129,6 +124,8 @@ fn gen_page(module: &str) -> String {
     <meta charset="UTF-8" />
   </head>
   <body>
+    <div id="main">
+    </div>
     <!-- Note the usage of `type=module` here as this is an ES6 module -->
     <script type="module">
       import init from "{}";
@@ -141,3 +138,35 @@ fn gen_page(module: &str) -> String {
         module
     )
 }
+
+// use binary_install::{Cache, Download};
+
+// /// Attempts to find `wasm-opt` in `PATH` locally, or failing that downloads a
+// /// precompiled binary.
+// ///
+// /// Returns `Some` if a binary was found or it was successfully downloaded.
+// /// Returns `None` if a binary wasn't found in `PATH` and this platform doesn't
+// /// have precompiled binaries. Returns an error if we failed to download the
+// /// binary.
+// pub fn find_wasm_opt(
+//     cache: &Cache,
+//     install_permitted: bool,
+// ) -> Result<install::Status, failure::Error> {
+//     // First attempt to look up in PATH. If found assume it works.
+//     if let Ok(path) = which::which("wasm-opt") {
+//         PBAR.info(&format!("found wasm-opt at {:?}", path));
+
+//         match path.as_path().parent() {
+//             Some(path) => return Ok(install::Status::Found(Download::at(path))),
+//             None => {}
+//         }
+//     }
+
+//     let version = "version_78";
+//     Ok(install::download_prebuilt(
+//         &install::Tool::WasmOpt,
+//         cache,
+//         version,
+//         install_permitted,
+//     )?)
+// }

+ 44 - 5
src/cli.rs

@@ -8,22 +8,24 @@ pub struct LaunchOptions {
 }
 
 /// The various kinds of commands that `wasm-pack` can execute.
-#[derive(FromArgs, PartialEq, Debug)]
+#[derive(FromArgs, PartialEq, Debug, Clone)]
 #[argh(subcommand)]
 pub enum LaunchCommand {
     Develop(DevelopOptions),
     Build(BuildOptions),
+    Translate(TranslateOptions),
     Test(TestOptions),
     Publish(PublishOptions),
+    Studio(StudioOptions),
 }
 
 /// Publish your yew application to Github Pages, Netlify, or S3
-#[derive(FromArgs, PartialEq, Debug)]
+#[derive(FromArgs, PartialEq, Debug, Clone)]
 #[argh(subcommand, name = "publish")]
 pub struct PublishOptions {}
 
 /// 🔬 test your yew application!
-#[derive(FromArgs, PartialEq, Debug)]
+#[derive(FromArgs, PartialEq, Debug, Clone)]
 #[argh(subcommand, name = "test")]
 pub struct TestOptions {
     /// an example in the crate
@@ -35,7 +37,7 @@ pub struct TestOptions {
 #[derive(FromArgs, PartialEq, Debug, Clone)]
 #[argh(subcommand, name = "build")]
 pub struct BuildOptions {
-    /// an optional direction which is "up" by default
+    /// the directory output
     #[argh(option, short = 'o', default = "String::from(\"public\")")]
     pub outdir: String,
 
@@ -46,10 +48,18 @@ pub struct BuildOptions {
     /// develop in release mode
     #[argh(switch, short = 'r')]
     pub release: bool,
+
+    /// hydrate the `dioxusroot` element with this content
+    #[argh(option, short = 'h')]
+    pub hydrate: Option<String>,
+
+    /// custom template
+    #[argh(option, short = 't')]
+    pub template: Option<String>,
 }
 
 /// 🛠 Start a development server
-#[derive(FromArgs, PartialEq, Debug)]
+#[derive(FromArgs, PartialEq, Debug, Clone)]
 #[argh(subcommand, name = "develop")]
 pub struct DevelopOptions {
     /// an example in the crate
@@ -59,4 +69,33 @@ pub struct DevelopOptions {
     /// develop in release mode
     #[argh(switch, short = 'r')]
     pub release: bool,
+
+    /// hydrate the `dioxusroot` element with this content
+    #[argh(option, short = 'h')]
+    pub hydrate: Option<String>,
+
+    /// custom template
+    #[argh(option, short = 't')]
+    pub template: Option<String>,
+}
+
+/// 🛠 Translate some 3rd party template into rsx
+#[derive(FromArgs, PartialEq, Debug, Clone)]
+#[argh(subcommand, name = "translate")]
+pub struct TranslateOptions {
+    /// an example in the crate
+    #[argh(option, short = 'f')]
+    pub file: Option<String>,
+
+    /// an example in the crate
+    #[argh(option, short = 't')]
+    pub text: Option<String>,
+
+    /// whether or not to jump
+    #[argh(switch, short = 'c')]
+    pub component: bool,
 }
+/// 🛠 Translate some 3rd party template into rsx
+#[derive(FromArgs, PartialEq, Debug, Clone)]
+#[argh(subcommand, name = "studio")]
+pub struct StudioOptions {}

+ 0 - 0
src/cmd/build.rs


+ 0 - 0
src/cmd/mod.rs


+ 0 - 0
src/cmd/serve.rs


+ 0 - 0
src/cmd/studio.rs


+ 0 - 0
src/watch.rs → src/cmd/watch.rs


+ 3 - 2
src/config.rs

@@ -1,11 +1,12 @@
 use crate::{
     cli::{BuildOptions, DevelopOptions},
     error::Result,
+    LaunchCommand,
 };
 use std::{io::Write, path::PathBuf, process::Command};
 
 #[derive(Debug, Clone)]
-pub struct Config {
+pub struct CrateConfig {
     pub out_dir: PathBuf,
     pub crate_dir: PathBuf,
     pub workspace_dir: PathBuf,
@@ -23,7 +24,7 @@ pub enum ExecutableType {
     Example(String),
 }
 
-impl Config {
+impl CrateConfig {
     pub fn new() -> Result<Self> {
         let crate_dir = crate::cargo::crate_root()?;
         let workspace_dir = crate::cargo::workspace_root()?;

+ 0 - 111
src/develop.rs

@@ -1,111 +0,0 @@
-use crate::{builder::BuildConfig, cli::DevelopOptions, config::Config, error::Result};
-use async_std::prelude::FutureExt;
-
-use async_std::future;
-use async_std::prelude::*;
-
-use log::info;
-use notify::{RecommendedWatcher, RecursiveMode, Watcher};
-use std::path::PathBuf;
-use std::time::Duration;
-
-pub struct DevelopConfig {}
-impl Into<DevelopConfig> for DevelopOptions {
-    fn into(self) -> DevelopConfig {
-        DevelopConfig {}
-    }
-}
-
-pub async fn start(config: &Config, _options: &DevelopConfig) -> Result<()> {
-    log::info!("Starting development server 🚀");
-
-    let Config { out_dir, .. } = config;
-
-    // Spawn the server onto a seperate task
-    // This lets the task progress while we handle file updates
-    let server = async_std::task::spawn(launch_server(out_dir.clone()));
-    let watcher = async_std::task::spawn(watch_directory(config.clone()));
-
-    match server.race(watcher).await {
-        Err(e) => log::warn!("Error running development server, {:?}", e),
-        _ => {}
-    }
-
-    Ok(())
-}
-
-async fn watch_directory(config: Config) -> Result<()> {
-    // Create a channel to receive the events.
-    let (watcher_tx, watcher_rx) = async_std::channel::bounded(100);
-
-    // Automatically select the best implementation for your platform.
-    // You can also access each implementation directly e.g. INotifyWatcher.
-    let mut watcher: RecommendedWatcher = Watcher::new(move |res| {
-        async_std::task::block_on(watcher_tx.send(res));
-    })
-    .expect("failed to make watcher");
-
-    let src_dir = crate::cargo::crate_root()?;
-
-    // Add a path to be watched. All files and directories at that path and
-    // below will be monitored for changes.
-    watcher
-        .watch(&src_dir.join("src"), RecursiveMode::Recursive)
-        .expect("Failed to watch dir");
-
-    watcher
-        .watch(&src_dir.join("examples"), RecursiveMode::Recursive)
-        .expect("Failed to watch dir");
-
-    let build_config = BuildConfig::default();
-
-    'run: loop {
-        crate::builder::build(&config, &build_config)?;
-
-        // Wait for the message with a debounce
-        let _msg = watcher_rx
-            .recv()
-            .join(future::ready(1_usize).delay(Duration::from_millis(2000)))
-            .await;
-
-        info!("File updated, rebuilding app");
-    }
-    Ok(())
-}
-
-async fn launch_server(outdir: PathBuf) -> Result<()> {
-    let _crate_dir = crate::cargo::crate_root()?;
-    let _workspace_dir = crate::cargo::workspace_root()?;
-
-    let mut app = tide::with_state(ServerState::new(outdir.to_owned()));
-    let p = outdir.display().to_string();
-
-    app.at("/")
-        .get(|req: tide::Request<ServerState>| async move {
-            log::info!("Connected to development server");
-            let state = req.state();
-            Ok(tide::Body::from_file(state.serv_path.clone().join("index.html")).await?)
-        })
-        .serve_dir(p)?;
-
-    let port = "8080";
-    let serve_addr = format!("0.0.0.0:{}", port);
-    // let serve_addr = format!("127.0.0.1:{}", port);
-
-    info!("App available at http://{}", serve_addr);
-    app.listen(serve_addr).await?;
-    Ok(())
-}
-
-/// https://github.com/http-rs/tide/blob/main/examples/state.rs
-/// Tide seems to prefer using state instead of injecting into the app closure
-/// The app closure needs to be static and
-#[derive(Clone)]
-struct ServerState {
-    serv_path: PathBuf,
-}
-impl ServerState {
-    fn new(serv_path: PathBuf) -> Self {
-        Self { serv_path }
-    }
-}

+ 148 - 0
src/develop/develop.rs

@@ -0,0 +1,148 @@
+use crate::{cli::DevelopOptions, config::CrateConfig, error::Result};
+use async_std::prelude::FutureExt;
+
+use log::info;
+use notify::{RecommendedWatcher, RecursiveMode, Watcher};
+use std::path::PathBuf;
+use std::sync::atomic::AtomicBool;
+use std::sync::Arc;
+use tide::http::mime::HTML;
+use tide::http::Mime;
+
+pub struct DevelopState {
+    //
+    reload_on_change: bool,
+}
+
+pub async fn develop(options: DevelopOptions) -> Result<()> {
+    //
+    log::info!("Starting development server 🚀");
+    let mut cfg = CrateConfig::new()?;
+    cfg.with_develop_options(&options);
+
+    let out_dir = cfg.out_dir.clone();
+
+    let is_err = Arc::new(AtomicBool::new(false));
+
+    // Spawn the server onto a seperate task
+    // This lets the task progress while we handle file updates
+    let server = async_std::task::spawn(launch_server(out_dir, is_err.clone()));
+    let watcher = async_std::task::spawn(watch_directory(cfg.clone(), is_err.clone()));
+
+    match server.race(watcher).await {
+        Err(e) => log::warn!("Error running development server, {:?}", e),
+        _ => {}
+    }
+
+    Ok(())
+}
+
+async fn watch_directory(config: CrateConfig, is_err: ErrStatus) -> Result<()> {
+    // Create a channel to receive the events.
+    let (watcher_tx, watcher_rx) = async_std::channel::bounded(100);
+
+    // Automatically select the best implementation for your platform.
+    // You can also access each implementation directly e.g. INotifyWatcher.
+    let mut watcher: RecommendedWatcher = Watcher::new(move |res| {
+<<<<<<< HEAD
+        async_std::task::block_on(watcher_tx.send(res));
+=======
+        // send an event
+        let _ = async_std::task::block_on(watcher_tx.send(res));
+>>>>>>> 9451713 (wip: studio upgrades)
+    })
+    .expect("failed to make watcher");
+
+    let src_dir = crate::cargo::crate_root()?;
+
+    // Add a path to be watched. All files and directories at that path and
+    // below will be monitored for changes.
+    watcher
+        .watch(&src_dir.join("src"), RecursiveMode::Recursive)
+        .expect("Failed to watch dir");
+
+    match watcher.watch(&src_dir.join("examples"), RecursiveMode::Recursive) {
+        Ok(_) => {}
+        Err(e) => log::warn!("Failed to watch examples dir, {:?}", e),
+    }
+
+    'run: loop {
+        match crate::builder::build(&config) {
+            Ok(_) => {
+                is_err.store(false, std::sync::atomic::Ordering::Relaxed);
+                async_std::task::sleep(std::time::Duration::from_millis(500)).await;
+            }
+            Err(err) => is_err.store(true, std::sync::atomic::Ordering::Relaxed),
+        };
+
+        let mut msg = None;
+        loop {
+            let new_msg = watcher_rx.recv().await.unwrap().unwrap();
+            if !watcher_rx.is_empty() {
+                msg = Some(new_msg);
+                break;
+            }
+        }
+
+        info!("File updated, rebuilding app");
+    }
+    Ok(())
+}
+
+async fn launch_server(outdir: PathBuf, is_err: ErrStatus) -> Result<()> {
+    let _crate_dir = crate::cargo::crate_root()?;
+    let _workspace_dir = crate::cargo::workspace_root()?;
+
+    let mut app = tide::with_state(ServerState::new(outdir.to_owned(), is_err));
+
+    let file_path = format!("{}/index.html", outdir.display());
+    log::info!("Serving {}", file_path);
+    let p = outdir.display().to_string();
+
+    app.at("/")
+        .get(|req: tide::Request<ServerState>| async move {
+            log::info!("Connected to development server");
+            let state = req.state();
+
+            match state.is_err.load(std::sync::atomic::Ordering::Relaxed) {
+                true => {
+                    //
+                    let mut resp =
+                        tide::Body::from_string(format!(include_str!("../err.html"), err = "_"));
+                    resp.set_mime(HTML);
+
+                    Ok(resp)
+                }
+                false => {
+                    Ok(tide::Body::from_file(state.serv_path.clone().join("index.html")).await?)
+                }
+            }
+        })
+        .serve_dir(p)?;
+    // .serve_file(file_path)
+    // .unwrap();
+
+    let port = "8080";
+    let serve_addr = format!("127.0.0.1:{}", port);
+
+    info!("App available at http://{}/", serve_addr);
+    app.listen(serve_addr).await?;
+    Ok(())
+}
+
+/// https://github.com/http-rs/tide/blob/main/examples/state.rs
+/// Tide seems to prefer using state instead of injecting into the app closure
+/// The app closure needs to be static and
+#[derive(Clone)]
+struct ServerState {
+    serv_path: PathBuf,
+    is_err: ErrStatus,
+}
+
+type ErrStatus = Arc<AtomicBool>;
+
+impl ServerState {
+    fn new(serv_path: PathBuf, is_err: ErrStatus) -> Self {
+        Self { serv_path, is_err }
+    }
+}

+ 0 - 0
src/develop/draw.rs


+ 0 - 0
src/develop/events.rs


+ 164 - 0
src/develop/studio.rs

@@ -0,0 +1,164 @@
+//! It's better to store all the configuration in one spot
+
+use tui::{
+    backend::{Backend, CrosstermBackend},
+    layout::{Constraint, Direction, Layout, Rect},
+    style::{Color, Modifier, Style},
+    symbols,
+    text::{Span, Spans},
+    widgets::canvas::{Canvas, Line, Map, MapResolution, Rectangle},
+    widgets::{
+        Axis, BarChart, Block, BorderType, Borders, Cell, Chart, Dataset, Gauge, LineGauge, List,
+        ListItem, Paragraph, Row, Sparkline, Table, Tabs, Wrap,
+    },
+    Frame, Terminal,
+};
+
+use crate::*;
+use std::{any::Any, io::Write, path::PathBuf, process::Command};
+
+pub struct Cfg {
+    command: LaunchOptions,
+    headless: bool,
+    example: Option<String>,
+    outdir: Option<String>,
+    release: bool,
+    hydrate: Option<String>,
+    template: Option<String>,
+    translate_file: Option<String>,
+    crate_config: Option<CrateConfig>,
+    should_quit: bool,
+}
+
+pub async fn start(options: DevelopOptions) -> Result<()> {
+    let mut state = Cfg {
+        command: todo!(),
+        headless: todo!(),
+        example: todo!(),
+        outdir: todo!(),
+        release: todo!(),
+        hydrate: todo!(),
+        template: todo!(),
+        translate_file: todo!(),
+        crate_config: todo!(),
+        should_quit: false,
+    };
+
+    crossterm::terminal::enable_raw_mode()?;
+
+    let backend = CrosstermBackend::new(std::io::stdout());
+    let mut terminal = Terminal::new(backend).unwrap();
+
+    // Setup input handling
+    // let (tx, rx) = futures::channel::mpsc::unbounded();
+    let tick_rate = std::time::Duration::from_millis(100);
+
+    let mut prev_time = std::time::Instant::now();
+    while !state.should_quit {
+        let next_time = prev_time + tick_rate;
+        let now = std::time::Instant::now();
+
+        let diff = next_time - std::time::Instant::now();
+    }
+
+    Ok(())
+}
+
+struct TuiStudio {
+    cfg: Cfg,
+    hook_idx: usize,
+    hooks: Vec<Box<dyn Any>>,
+}
+impl TuiStudio {
+    fn use_hook<F: 'static>(&mut self, f: impl FnOnce() -> F) -> &mut F {
+        if self.hook_idx == self.hooks.len() {
+            self.hooks.push(Box::new(f()));
+        }
+        let idx = self.hook_idx;
+        self.hook_idx += 1;
+        let hook = self.hooks.get_mut(idx).unwrap();
+        let r = hook.downcast_mut::<F>().unwrap();
+        r
+    }
+}
+
+impl TuiStudio {
+    fn event_handler(&self, action: crossterm::event::Event) -> anyhow::Result<()> {
+        match action {
+            crossterm::event::Event::Key(_) => {}
+            crossterm::event::Event::Mouse(_) => {}
+            crossterm::event::Event::Resize(_, _) => {}
+        }
+        Ok(())
+    }
+
+    fn handle_key(&mut self, key: crossterm::event::KeyEvent) {}
+
+    fn tick(&mut self) {}
+
+    fn should_quit(&self) -> bool {
+        false
+    }
+
+    fn render<B: tui::backend::Backend>(&mut self, f: &mut tui::Frame<B>) {
+        self.hook_idx = 0;
+
+        // Wrapping block for a group
+        // Just draw the block and the group on the same area and build the group
+        // with at least a margin of 1
+        let size = f.size();
+        let block = Block::default()
+            .borders(Borders::ALL)
+            .title("Main block with round corners")
+            .border_type(BorderType::Rounded);
+        f.render_widget(block, size);
+        let chunks = Layout::default()
+            .direction(Direction::Vertical)
+            .margin(4)
+            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+            .split(f.size());
+
+        let top_chunks = Layout::default()
+            .direction(Direction::Horizontal)
+            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+            .split(chunks[0]);
+        let block = Block::default()
+            .title(vec![
+                Span::styled("With", Style::default().fg(Color::Yellow)),
+                Span::from(" background"),
+            ])
+            .style(Style::default().bg(Color::Green));
+        f.render_widget(block, top_chunks[0]);
+
+        let block = Block::default().title(Span::styled(
+            "Styled title",
+            Style::default()
+                .fg(Color::White)
+                .bg(Color::Red)
+                .add_modifier(Modifier::BOLD),
+        ));
+        f.render_widget(block, top_chunks[1]);
+
+        let bottom_chunks = Layout::default()
+            .direction(Direction::Horizontal)
+            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+            .split(chunks[1]);
+        let block = Block::default().title("With borders").borders(Borders::ALL);
+        f.render_widget(block, bottom_chunks[0]);
+        let block = Block::default()
+            .title("With styled borders and doubled borders")
+            .border_style(Style::default().fg(Color::Cyan))
+            .borders(Borders::LEFT | Borders::RIGHT)
+            .border_type(BorderType::Double);
+        f.render_widget(block, bottom_chunks[1]);
+    }
+}
+
+impl TuiStudio {
+    fn render_list<B: tui::backend::Backend>(&mut self, f: &mut tui::Frame<B>) {
+        let options = [
+            "Bundle", "Develop",
+            //
+        ];
+    }
+}

+ 19 - 0
src/err.html

@@ -0,0 +1,19 @@
+<html>
+
+<head></head>
+
+<body>
+    <div>
+        <h1>
+            Sorry, but building your application failed.
+        </h1>
+        <p>
+            Here's the error:
+        </p>
+        <code>
+            {err}
+        </code>
+    </div>
+</body>
+
+</html>

+ 3 - 0
src/error.rs

@@ -14,6 +14,9 @@ pub enum Error {
     #[error("Failed to write error")]
     FailedToWrite,
 
+    #[error("Building project failed")]
+    BuildFailed(String),
+
     #[error("Failed to write error")]
     CargoError(String),
 

+ 0 - 0
src/helpers/extract_svgs.rs


+ 181 - 0
src/helpers/to_component.rs

@@ -0,0 +1,181 @@
+//! Intelligently converts html to rsx with appropraite transformations and extractions.
+//!
+//! - [*] Creates a component
+//! - [ ] Extracts svgs
+//! - [ ] Attempts to extract lists
+
+use std::{
+    fmt::{Display, Formatter},
+    io::Write,
+};
+
+use anyhow::Result;
+
+use html_parser::{Dom, Element, Node};
+
+pub fn convert_html_to_component(html: &str) -> Result<ComponentRenderer> {
+    Ok(ComponentRenderer {
+        dom: Dom::parse(html)?,
+        icon_index: 0,
+    })
+}
+
+pub struct ComponentRenderer {
+    dom: Dom,
+    icon_index: usize,
+}
+
+impl Display for ComponentRenderer {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        writeln!(
+            f,
+            r##"
+fn component(cx: Scope) -> Element {{
+    cx.render(rsx!("##
+        )?;
+        let mut svg_nodes = vec![];
+
+        let mut svg_idx = 0;
+        for child in &self.dom.children {
+            render_child(f, child, 2, &mut svg_nodes, true, &mut svg_idx)?;
+        }
+        write!(
+            f,
+            r##"    ))
+}}"##
+        )?;
+
+        if svg_idx == 0 {
+            return Ok(());
+        }
+
+        writeln!(f, "\n\nmod icons {{")?;
+
+        let mut id = 0;
+        while let Some(svg) = svg_nodes.pop() {
+            writeln!(
+                f,
+                r##"    pub(super) fn icon_{}(cx: Scope) -> Element {{
+        cx.render(rsx!("##,
+                id
+            )?;
+            write_tabs(f, 3)?;
+
+            render_element(f, svg, 3, &mut svg_nodes, false, &mut 0)?;
+            writeln!(f, "\t\t))\n\t}}\n")?;
+            id += 1;
+        }
+
+        writeln!(f, "}}")?;
+
+        Ok(())
+    }
+}
+
+fn render_child<'a>(
+    f: &mut Formatter<'_>,
+    child: &'a Node,
+    il: u32,
+    svg_buffer: &mut Vec<&'a Element>,
+    skip_svg: bool,
+    svg_idx: &mut usize,
+) -> std::fmt::Result {
+    write_tabs(f, il)?;
+    match child {
+        Node::Text(t) => writeln!(f, "\"{}\"", t)?,
+        Node::Comment(e) => writeln!(f, "/* {} */", e)?,
+        Node::Element(el) => render_element(f, el, il, svg_buffer, skip_svg, svg_idx)?,
+    };
+    Ok(())
+}
+
+fn render_element<'a>(
+    f: &mut Formatter<'_>,
+    el: &'a Element,
+    il: u32,
+    svg_buffer: &mut Vec<&'a Element>,
+    skip_svg: bool,
+    svg_idx: &mut usize,
+) -> std::fmt::Result {
+    if el.name == "svg" && skip_svg {
+        svg_buffer.push(el);
+        // todo: attach the right icon ID
+        writeln!(f, "icons::icon_{} {{}}", svg_idx)?;
+        *svg_idx += 1;
+        return Ok(());
+    }
+
+    // open the tag
+    write!(f, "{} {{ ", &el.name)?;
+
+    // todo: dioxus will eventually support classnames
+    // for now, just write them with a space between each
+    let class_iter = &mut el.classes.iter();
+    if let Some(first_class) = class_iter.next() {
+        write!(f, "class: \"{}", first_class)?;
+        for next_class in class_iter {
+            write!(f, " {}", next_class)?;
+        }
+        write!(f, "\",")?;
+    }
+    write!(f, "\n")?;
+
+    // write the attributes
+    if let Some(id) = &el.id {
+        write_tabs(f, il + 1)?;
+        writeln!(f, "id: \"{}\",", id)?;
+    }
+
+    for (name, value) in &el.attributes {
+        write_tabs(f, il + 1)?;
+
+        use convert_case::{Case, Casing};
+        if name.chars().any(|ch| ch.is_ascii_uppercase() || ch == '-') {
+            let new_name = name.to_case(Case::Snake);
+            match value {
+                Some(val) => writeln!(f, "{}: \"{}\",", new_name, val)?,
+                None => writeln!(f, "{}: \"\",", new_name)?,
+            }
+        } else {
+            match name.as_str() {
+                "for" | "async" | "type" | "as" => write!(f, "r#")?,
+                _ => {}
+            }
+
+            match value {
+                Some(val) => writeln!(f, "{}: \"{}\",", name, val)?,
+                None => writeln!(f, "{}: \"\",", name)?,
+            }
+        }
+    }
+
+    // now the children
+    for child in &el.children {
+        render_child(f, child, il + 1, svg_buffer, skip_svg, svg_idx)?;
+    }
+
+    // close the tag
+    write_tabs(f, il)?;
+    writeln!(f, "}}")?;
+    Ok(())
+}
+
+fn write_tabs(f: &mut Formatter, num: u32) -> std::fmt::Result {
+    for _ in 0..num {
+        write!(f, "    ")?
+    }
+    Ok(())
+}
+
+#[test]
+fn generates_svgs() {
+    let st = include_str!("../../tests/svg.html");
+
+    let out = format!("{:}", convert_html_to_component(st).unwrap());
+    dbg!(&out);
+
+    std::fs::File::create("svg_rsx.rs")
+        .unwrap()
+        .write_all(out.as_bytes())
+        .unwrap();
+}

+ 128 - 0
src/helpers/translate.rs

@@ -0,0 +1,128 @@
+use std::fmt::{Display, Formatter};
+
+use anyhow::Result;
+
+use html_parser::{Dom, Node};
+
+pub fn translate_from_html_file(target: &str) -> Result<RsxRenderer> {
+    use std::fs::File;
+    use std::io::Read;
+    let mut file = File::open(target).unwrap();
+
+    let mut contents = String::new();
+    file.read_to_string(&mut contents)
+        .expect("Failed to read your file.");
+    translate_from_html_to_rsx(&contents, true)
+}
+
+pub fn translate_from_html_to_rsx(html: &str, as_call: bool) -> Result<RsxRenderer> {
+    let contents = Dom::parse(html)?;
+    let renderer = RsxRenderer {
+        as_call,
+        dom: contents,
+    };
+    Ok(renderer)
+}
+
+pub struct RsxRenderer {
+    dom: Dom,
+    as_call: bool,
+}
+
+impl Display for RsxRenderer {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        if self.as_call {
+            writeln!(f, r##"use dioxus::prelude::*;"##)?;
+            writeln!(
+                f,
+                r##"
+fn component(cx: Scope) -> Element {{
+    cx.render(rsx!(
+"##
+            )?;
+        }
+        for child in &self.dom.children {
+            render_child(f, child, 1)?;
+        }
+        if self.as_call {
+            write!(
+                f,
+                r##"
+    )
+)            
+            "##
+            )?;
+        }
+        Ok(())
+    }
+}
+
+fn render_child(f: &mut Formatter<'_>, child: &Node, il: u32) -> std::fmt::Result {
+    write_tabs(f, il);
+    match child {
+        Node::Text(t) => writeln!(f, "\"{}\"", t)?,
+        Node::Comment(e) => writeln!(f, "/* {} */", e)?,
+        Node::Element(el) => {
+            // open the tag
+            write!(f, "{} {{ ", &el.name)?;
+
+            // todo: dioxus will eventually support classnames
+            // for now, just write them with a space between each
+            let class_iter = &mut el.classes.iter();
+            if let Some(first_class) = class_iter.next() {
+                write!(f, "class: \"{}", first_class)?;
+                for next_class in class_iter {
+                    write!(f, " {}", next_class)?;
+                }
+                write!(f, "\",")?;
+            }
+            write!(f, "\n")?;
+
+            // write the attributes
+            if let Some(id) = &el.id {
+                write_tabs(f, il + 1)?;
+                writeln!(f, "id: \"{}\",", id)?;
+            }
+
+            for (name, value) in &el.attributes {
+                write_tabs(f, il + 1)?;
+
+                use convert_case::{Case, Casing};
+                if name.chars().any(|ch| ch.is_ascii_uppercase() || ch == '-') {
+                    let new_name = name.to_case(Case::Snake);
+                    match value {
+                        Some(val) => writeln!(f, "{}: \"{}\",", new_name, val)?,
+                        None => writeln!(f, "{}: \"\",", new_name)?,
+                    }
+                } else {
+                    match name.as_str() {
+                        "for" | "async" | "type" | "as" => write!(f, "r#")?,
+                        _ => {}
+                    }
+
+                    match value {
+                        Some(val) => writeln!(f, "{}: \"{}\",", name, val)?,
+                        None => writeln!(f, "{}: \"\",", name)?,
+                    }
+                }
+            }
+
+            // now the children
+            for child in &el.children {
+                render_child(f, child, il + 1)?;
+            }
+
+            // close the tag
+            write_tabs(f, il)?;
+            writeln!(f, "}}")?;
+        }
+    };
+    Ok(())
+}
+
+fn write_tabs(f: &mut Formatter, num: u32) -> std::fmt::Result {
+    for _ in 0..num {
+        write!(f, "    ")?
+    }
+    Ok(())
+}

+ 0 - 8
src/lib.rs

@@ -1,8 +0,0 @@
-pub mod builder;
-pub mod cargo;
-pub mod cli;
-pub mod config;
-pub mod develop;
-pub mod error;
-pub mod logging;
-pub mod watch;

+ 0 - 14
src/logging.rs

@@ -1,5 +1,4 @@
 use fern::colors::{Color, ColoredLevelConfig};
-use log::debug;
 
 pub fn set_up_logging() {
     // configure colors for the whole line
@@ -29,21 +28,8 @@ pub fn set_up_logging() {
                 message = message,
             ));
         })
-        // set the default log level. to filter out verbose log messages from dependencies, set
-        // this to Warn and overwrite the log level for your crate.
         .level(log::LevelFilter::Info)
-        // .level(log::LevelFilter::Warn)
-        // change log levels for individual modules. Note: This looks for the record's target
-        // field which defaults to the module path but can be overwritten with the `target`
-        // parameter:
-        // `info!(target="special_target", "This log message is about special_target");`
-        // .level_for("dioxus", log::LevelFilter::Debug)
-        // .level_for("dioxus", log::LevelFilter::Info)
-        // .level_for("pretty_colored", log::LevelFilter::Trace)
-        // output to stdout
         .chain(std::io::stdout())
         .apply()
         .unwrap();
-
-    debug!("finished setting up logging! yay!");
 }

+ 85 - 16
src/main.rs

@@ -1,28 +1,97 @@
-use dioxus_studio as diopack;
-use dioxus_studio::cli::{LaunchCommand, LaunchOptions};
+mod builder;
+mod cargo;
+mod cli;
+mod config;
+mod error;
+mod logging;
+mod helpers {
+    pub mod extract_svgs;
+    pub mod to_component;
+    pub mod translate;
+}
 
-#[async_std::main]
-async fn main() -> diopack::error::Result<()> {
-    diopack::logging::set_up_logging();
+mod watch;
+mod develop {
+    pub mod develop;
+    pub mod draw;
+    pub mod events;
+    pub mod studio;
+}
 
-    let opts: LaunchOptions = argh::from_env();
-    let mut config = diopack::config::Config::new()?;
+use std::path::PathBuf;
+use structopt::StructOpt;
 
-    match opts.command {
-        LaunchCommand::Build(options) => {
-            config.with_build_options(&options);
-            diopack::builder::build(&config, &(options.into()))?;
-        }
+#[async_std::main]
+async fn main() -> Result<()> {
+    set_up_logging();
+    let args = Args::from_args();
 
-        LaunchCommand::Develop(options) => {
-            config.with_develop_options(&options);
-            diopack::develop::start(&config, &(options.into())).await?;
+    match args.command {
+        LaunchCommand::Develop(cfg) => {
+            develop::develop::develop(cfg).await?;
+        }
+        // LaunchCommand::Develop(cfg) => develop::studio::start(cfg).await?,
+        LaunchCommand::Build(opts) => {
+            let mut cfg = CrateConfig::new()?;
+            cfg.with_build_options(&opts);
+            builder::build(&cfg)?;
         }
 
+        LaunchCommand::Translate(cfg) => {
+            let TranslateOptions {
+                file,
+                text,
+                component,
+            } = cfg;
+
+            match component {
+                true => {
+                    let f = helpers::to_component::convert_html_to_component(&text.unwrap())?;
+                    println!("{}", f);
+                }
+                false => {
+                    let renderer = match (file, text) {
+                        (None, Some(text)) => translate::translate_from_html_to_rsx(&text, false)?,
+                        (Some(file), None) => translate::translate_from_html_file(&file)?,
+                        _ => panic!("Must select either file or text - not both or none!"),
+                    };
+
+                    println!("{}", renderer);
+                }
+            }
+        }
         _ => {
-            todo!("Command not currently implemented");
+            todo!("Those commands are not yet supported");
         }
     }
 
     Ok(())
 }
+
+/// Build, bundle & ship your Rust WASM application to the web.
+#[derive(StructOpt)]
+#[structopt(name = "trunk")]
+struct Args {
+    #[structopt(subcommand)]
+    command: TrunkSubcommands,
+    /// Path to the Trunk config file [default: Trunk.toml]
+    #[structopt(long, parse(from_os_str), env = "TRUNK_CONFIG")]
+    pub config: Option<PathBuf>,
+    /// Enable verbose logging.
+    #[structopt(short)]
+    pub v: bool,
+}
+
+#[derive(StructOpt)]
+enum TrunkSubcommands {
+    /// Build the Rust WASM app and all of its assets.
+    Build(cmd::build::Build),
+    /// Build & watch the Rust WASM app and all of its assets.
+    Watch(cmd::watch::Watch),
+    /// Build, watch & serve the Rust WASM app and all of its assets.
+    Serve(cmd::serve::Serve),
+    /// Clean output artifacts.
+    Clean(cmd::clean::Clean),
+    /// Trunk config controls.
+    Config(cmd::config::Config),
+}

+ 30 - 0
tests/svg.html

@@ -0,0 +1,30 @@
+<div>
+    <svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
+    <path
+        fill-rule="evenodd"
+        d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
+        clip-rule="evenodd"
+    />
+    </svg>
+    <svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
+    <path
+        fill-rule="evenodd"
+        d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
+        clip-rule="evenodd"
+    />
+    </svg>
+    <svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
+    <path
+        fill-rule="evenodd"
+        d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
+        clip-rule="evenodd"
+    />
+    </svg>
+    <svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
+    <path
+        fill-rule="evenodd"
+        d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
+        clip-rule="evenodd"
+    />
+    </svg>
+</div>

+ 32 - 0
tests/test.html

@@ -0,0 +1,32 @@
+<section class="text-gray-600 body-font">
+    <div class="container px-5 py-24 mx-auto">
+        <div class="flex flex-wrap -mx-4 -mb-10 text-center">
+            <div class="sm:w-1/2 mb-10 px-4">
+                <div class="rounded-lg h-64 overflow-hidden">
+                    <img alt="content" class="object-cover object-center h-full w-full"
+                        src="https://dummyimage.com/1201x501">
+                </div>
+                <h2 class="title-font text-2xl font-medium text-gray-900 mt-6 mb-3">Buy YouTube Videos</h2>
+                <p class="leading-relaxed text-base">
+                    Williamsburg occupy sustainable snackwave gochujang. Pinterest cornhole brunch, slow-carb neutra
+                    irony.
+                </p>
+                <button
+                    class="flex mx-auto mt-6 text-white bg-indigo-500 border-0 py-2 px-5 focus:outline-none hover:bg-indigo-600 rounded">Button</button>
+            </div>
+            <div class="sm:w-1/2 mb-10 px-4">
+                <div class="rounded-lg h-64 overflow-hidden">
+                    <img alt="content" class="object-cover object-center h-full w-full"
+                        src="https://dummyimage.com/1202x502">
+                </div>
+                <h2 class="title-font text-2xl font-medium text-gray-900 mt-6 mb-3">The Catalyzer</h2>
+                <p class="leading-relaxed text-base">
+                    Williamsburg occupy sustainable snackwave gochujang. Pinterest
+                    cornhole brunch, slow-carb neutra irony.
+                </p>
+                <button
+                    class="flex mx-auto mt-6 text-white bg-indigo-500 border-0 py-2 px-5 focus:outline-none hover:bg-indigo-600 rounded">Button</button>
+            </div>
+        </div>
+    </div>
+</section>