From 5118a8174b850c25ccf4fd7c253cb6c330c4b2a0 Mon Sep 17 00:00:00 2001 From: "M. George Hansen" Date: Mon, 15 Jul 2024 08:36:52 -0700 Subject: [PATCH] chore: replace eslint & prettier w/ biomejs (#21) * chore: replace eslint & prettier w/ biomejs * fix syntax error in ci.yml workflow * ensure that build CI jobs only run if check job succeeds to save resources --- .eslintignore | 2 - .eslintrc.json | 23 - .github/workflows/ci.yml | 9 + .prettierignore | 2 - .prettierrc.json | 7 - biome.json | 36 + examples/personal-site/components/header.tsx | 30 +- examples/personal-site/components/layout.tsx | 89 +- examples/personal-site/components/navbar.tsx | 64 +- examples/personal-site/package-lock.json | 1654 ++---------- examples/personal-site/package.json | 23 +- examples/personal-site/pages/index.tsx | 33 +- examples/personal-site/pages/projects.tsx | 32 +- examples/personal-site/tsconfig.json | 30 +- examples/personal-site/websnacks.ts | 41 +- package-lock.json | 2404 ++---------------- package.json | 99 +- scripts/clean.ts | 32 +- src/build.ts | 124 +- src/cli/commands/build.ts | 28 +- src/cli/commands/dev.ts | 498 ++-- src/cli/index.ts | 157 +- src/cli/types.ts | 30 +- src/component.ts | 60 +- src/config.ts | 108 +- src/create-element.ts | 85 +- src/index.ts | 2 +- src/jsx.ts | 534 ++-- src/render.ts | 158 +- src/utils/decache-module.ts | 94 +- src/utils/error.ts | 2 +- src/utils/index.ts | 42 +- test/e2e/build.tsx | 252 +- test/e2e/dev.tsx | 270 +- test/helpers/e2e.ts | 182 +- test/lib/expect.ts | 256 +- test/lib/harness.ts | 154 +- test/lib/utils.ts | 108 +- test/run-e2e.ts | 18 +- test/run-tests.ts | 18 +- test/test-suites/rendering.tsx | 263 +- test/tsconfig.json | 10 +- tsconfig-base.json | 22 +- tsconfig.json | 14 +- 44 files changed, 2408 insertions(+), 5691 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json delete mode 100644 .prettierignore delete mode 100644 .prettierrc.json create mode 100644 biome.json diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index b947077..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -dist/ diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index b41d7cf..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint", "prettier"], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react/recommended", - "plugin:prettier/recommended" - ], - "settings": { - "react": { - "pragma": "createElement" - } - }, - "rules": { - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/ban-types": "off", - "react/prop-types": "off", - "react/jsx-key": "off" - } -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67483ed..bbabec6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,16 @@ on: branches: [mainline] jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm ci + - run: npm run check + build: + needs: check strategy: matrix: os: [windows-latest, ubuntu-latest, macos-latest] diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index b947077..0000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -dist/ diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 775cd9a..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "endOfLine": "lf", - "singleQuote": false, - "trailingComma": "all", - "tabWidth": 4, - "semi": true -} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..98f7223 --- /dev/null +++ b/biome.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", + "organizeImports": { + "enabled": true, + "ignore": ["dist", "node_modules", ".temp"] + }, + "formatter": { + "enabled": true, + "ignore": ["dist", "node_modules", ".temp"] + }, + "linter": { + "enabled": true, + "ignore": ["dist", "node_modules", ".temp"], + "rules": { + "recommended": true, + "style": { + "useShorthandFunctionType": "off" + }, + "correctness": { + "useJsxKeyInIterable": "off" + } + } + }, + "overrides": [ + { + "include": ["test"], + "linter": { + "rules": { + "a11y": { + "useHtmlLang": "off" + } + } + } + } + ] +} diff --git a/examples/personal-site/components/header.tsx b/examples/personal-site/components/header.tsx index 31cbc73..596dc66 100644 --- a/examples/personal-site/components/header.tsx +++ b/examples/personal-site/components/header.tsx @@ -1,25 +1,25 @@ import { stylesheet } from "typestyle"; -import { Component, createElement } from "websnacks"; +import { type Component, createElement } from "websnacks"; const styles = stylesheet({ - header: { - background: "#6c42bd", - color: "#fff", - padding: "32px", - textAlign: "center", - boxShadow: "0 1px 8px -3px #000", - }, - headline: { - fontSize: "28px", - }, + header: { + background: "#6c42bd", + color: "#fff", + padding: "32px", + textAlign: "center", + boxShadow: "0 1px 8px -3px #000", + }, + headline: { + fontSize: "28px", + }, }); export interface HeaderProps { - headline: string; + headline: string; } export const Header: Component = ({ headline }) => ( -
-

{headline}

-
+
+

{headline}

+
); diff --git a/examples/personal-site/components/layout.tsx b/examples/personal-site/components/layout.tsx index 3ca9dbf..821204a 100644 --- a/examples/personal-site/components/layout.tsx +++ b/examples/personal-site/components/layout.tsx @@ -1,6 +1,6 @@ import { normalize } from "csstips"; import { stylesheet } from "typestyle"; -import { Component, createElement } from "websnacks"; +import { type Component, createElement } from "websnacks"; import { stylesheetPath } from "../config"; import { Header } from "./header"; @@ -9,60 +9,57 @@ import { Navbar } from "./navbar"; normalize(); const styles = stylesheet({ - html: { - height: "100%", - }, - wrapper: { - height: "100%", - display: "flex", - flexDirection: "row", - margin: 0, - }, - main: { - flex: 1, - }, - mainBody: { - padding: "16px", - }, - navbar: { - display: "flex", - flex: "0 0 auto", - zIndex: 9, - }, + html: { + height: "100%", + }, + wrapper: { + height: "100%", + display: "flex", + flexDirection: "row", + margin: 0, + }, + main: { + flex: 1, + }, + mainBody: { + padding: "16px", + }, + navbar: { + display: "flex", + flex: "0 0 auto", + zIndex: 9, + }, }); const SITE_TITLE = "Example Site"; export interface LayoutProps { - headline?: string; + headline?: string; } export const Layout: Component = ({ children, headline }) => ( - - - - - {SITE_TITLE} - {headline && ` | ${headline}`} - - - - - + + + + + {SITE_TITLE} + {headline && ` | ${headline}`} + + + + + - -
- -
+ +
+ +
-
-
+
+
-
{children}
-
- - +
{children}
+
+ + ); diff --git a/examples/personal-site/components/navbar.tsx b/examples/personal-site/components/navbar.tsx index 044241d..da6c312 100644 --- a/examples/personal-site/components/navbar.tsx +++ b/examples/personal-site/components/navbar.tsx @@ -1,43 +1,43 @@ import { stylesheet } from "typestyle"; -import { Component, createElement } from "websnacks"; +import { type Component, createElement } from "websnacks"; const styles = stylesheet({ - navbar: { - minWidth: "140px", - borderRight: "1px solid #ddd", - background: "#fff", - }, - sectionTitle: { - color: "#333", - textAlign: "center", - borderBottom: "1px solid #333", - padding: "6px", - margin: "0 4px", - fontSize: "18px", - }, - linksList: { - padding: "3px 16px 0", - }, - linksListItem: { - padding: "6px", - }, + navbar: { + minWidth: "140px", + borderRight: "1px solid #ddd", + background: "#fff", + }, + sectionTitle: { + color: "#333", + textAlign: "center", + borderBottom: "1px solid #333", + padding: "6px", + margin: "0 4px", + fontSize: "18px", + }, + linksList: { + padding: "3px 16px 0", + }, + linksListItem: { + padding: "6px", + }, }); const links = [ - { title: "Home", href: "/" }, - { title: "Projects", href: "/projects" }, + { title: "Home", href: "/" }, + { title: "Projects", href: "/projects" }, ]; export const Navbar: Component = () => ( - ); diff --git a/examples/personal-site/package-lock.json b/examples/personal-site/package-lock.json index 9456666..daddaa8 100644 --- a/examples/personal-site/package-lock.json +++ b/examples/personal-site/package-lock.json @@ -1,1412 +1,246 @@ { - "name": "websnacks-example-personal-site", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "websnacks-example-personal-site", - "dependencies": { - "csstips": "^1.2.0", - "ts-node": "^8.10.1", - "typestyle": "^2.1.0", - "websnacks": "../../" - } - }, - "../..": { - "name": "@websnacksjs/websnacks", - "version": "0.2.0", - "license": "MPL-2.0", - "bin": { - "websnacks": "bin/websnacks.js" - }, - "devDependencies": { - "@types/node": "~18", - "@types/ws": "^7.4.0", - "@typescript-eslint/eslint-plugin": "^4.15.2", - "@typescript-eslint/parser": "^4.15.2", - "eslint": "^7.21.0", - "eslint-config-prettier": "^8.1.0", - "eslint-plugin-prettier": "^3.3.1", - "eslint-plugin-react": "^7.22.0", - "prettier": "=2.2.1", - "ts-node": "^9.1.1", - "typescript": "~4.2.2" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "node-watch": "^0.7.1", - "ws": "^7.4.3" - } - }, - "../../node_modules/@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.8.3" - } - }, - "../../node_modules/@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", - "dev": true - }, - "../../node_modules/@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.9.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "../../node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "../../node_modules/@types/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true - }, - "../../node_modules/@types/json-schema": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", - "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", - "dev": true - }, - "../../node_modules/@types/node": { - "version": "12.12.38", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.38.tgz", - "integrity": "sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==", - "dev": true - }, - "../../node_modules/@types/ws": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.4.tgz", - "integrity": "sha512-9S6Ask71vujkVyeEXKxjBSUV8ZUB0mjL5la4IncBoheu04bDaYyUKErh1BQcY9+WzOUOiKqz/OnpJHYckbMfNg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "../../node_modules/@typescript-eslint/eslint-plugin": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.31.0.tgz", - "integrity": "sha512-iIC0Pb8qDaoit+m80Ln/aaeu9zKQdOLF4SHcGLarSeY1gurW6aU4JsOPMjKQwXlw70MvWKZQc6S2NamA8SJ/gg==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "2.31.0", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "tsutils": "^3.17.1" - } - }, - "../../node_modules/@typescript-eslint/experimental-utils": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.31.0.tgz", - "integrity": "sha512-MI6IWkutLYQYTQgZ48IVnRXmLR/0Q6oAyJgiOror74arUMh7EWjJkADfirZhRsUMHeLJ85U2iySDwHTSnNi9vA==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.31.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - } - }, - "../../node_modules/@typescript-eslint/parser": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.31.0.tgz", - "integrity": "sha512-uph+w6xUOlyV2DLSC6o+fBDzZ5i7+3/TxAsH4h3eC64tlga57oMb96vVlXoMwjR/nN+xyWlsnxtbDkB46M2EPQ==", - "dev": true, - "dependencies": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.31.0", - "@typescript-eslint/typescript-estree": "2.31.0", - "eslint-visitor-keys": "^1.1.0" - } - }, - "../../node_modules/@typescript-eslint/typescript-estree": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.31.0.tgz", - "integrity": "sha512-vxW149bXFXXuBrAak0eKHOzbcu9cvi6iNcJDzEtOkRwGHxJG15chiAQAwhLOsk+86p9GTr/TziYvw+H9kMaIgA==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "eslint-visitor-keys": "^1.1.0", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^6.3.0", - "tsutils": "^3.17.1" - } - }, - "../../node_modules/acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", - "dev": true - }, - "../../node_modules/acorn-jsx": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", - "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", - "dev": true - }, - "../../node_modules/ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", - "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" - } - }, - "../../node_modules/ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "dependencies": { - "type-fest": "^0.11.0" - } - }, - "../../node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true - }, - "../../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 - }, - "../../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" - } - }, - "../../node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "../../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/astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "../../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/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "../../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 - }, - "../../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" - } - }, - "../../node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "../../node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - } - }, - "../../node_modules/cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, - "../../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": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "../../node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "../../node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "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/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "../../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" - } - }, - "../../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/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 - }, - "../../node_modules/eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.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", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - } - }, - "../../node_modules/eslint-config-prettier": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", - "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", - "dev": true, - "dependencies": { - "get-stdin": "^6.0.0" - } - }, - "../../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" - } - }, - "../../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" - } - }, - "../../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 - }, - "../../node_modules/eslint/node_modules/eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "../../node_modules/eslint/node_modules/regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "../../node_modules/espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - } - }, - "../../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 - }, - "../../node_modules/esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - } - }, - "../../node_modules/esquery/node_modules/estraverse": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", - "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", - "dev": true - }, - "../../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" - } - }, - "../../node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "../../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 - }, - "../../node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "../../node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "../../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/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - } - }, - "../../node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "dependencies": { - "flat-cache": "^2.0.1" - } - }, - "../../node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "../../node_modules/flat-cache/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - } - }, - "../../node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "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/get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "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" - } - }, - "../../node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - } - }, - "../../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" - } - }, - "../../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 - }, - "../../node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "../../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 - }, - "../../node_modules/import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "../../node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "../../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/inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - } - }, - "../../node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "dependencies": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "../../node_modules/inquirer/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "../../node_modules/inquirer/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" - } - }, - "../../node_modules/inquirer/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/inquirer/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 - }, - "../../node_modules/inquirer/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" - } - }, - "../../node_modules/inquirer/node_modules/supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - } - }, - "../../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 - }, - "../../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 - }, - "../../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" - } - }, - "../../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.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "../../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.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "../../node_modules/lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "../../node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "../../node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "../../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" - } - }, - "../../node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "../../node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - } - }, - "../../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/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "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/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "../../node_modules/node-watch": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.6.4.tgz", - "integrity": "sha512-cI6CHzivIFESe8djiK3Wh90CtWQBxLwMem8x8S+2GSvCvFgoMuOKVlfJtQ/2v3Afg3wOnHl/+tXotEs8z5vOrg==", - "optional": 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/onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - } - }, - "../../node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "../../node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "../../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" - } - }, - "../../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 - }, - "../../node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "../../node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "../../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 - }, - "../../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 - }, - "../../node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "../../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 - }, - "../../node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "../../node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "../../node_modules/rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - } - }, - "../../node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "../../node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "../../node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - } - }, - "../../node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "../../node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "../../node_modules/slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "../../node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "../../node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "../../node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "../../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.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "../../node_modules/string-width/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" - } - }, - "../../node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - } - }, - "../../node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "../../node_modules/strip-json-comments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", - "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", - "dev": true - }, - "../../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" - } - }, - "../../node_modules/table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - } - }, - "../../node_modules/table/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "../../node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "../../node_modules/table/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "../../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/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "../../node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - } - }, - "../../node_modules/ts-node": { - "version": "8.10.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.1.tgz", - "integrity": "sha512-bdNz1L4ekHiJul6SHtZWs1ujEKERJnHs4HxN7rjTyyVOFf3HaJ6sLqe6aPG62XTzAB/63pKRh5jTSWL0D7bsvw==", - "dev": true, - "dependencies": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - }, - "../../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.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - } - }, - "../../node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - } - }, - "../../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 - }, - "../../node_modules/typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", - "dev": true - }, - "../../node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "../../node_modules/v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", - "dev": true - }, - "../../node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - } - }, - "../../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 - }, - "../../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/write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1" - } - }, - "../../node_modules/ws": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", - "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==", - "optional": true - }, - "../../node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "node_modules/csstips": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/csstips/-/csstips-1.2.0.tgz", - "integrity": "sha512-2KgBibTljubrEuaiCNdJ0zcy6BmJck+J9YUufb+Hwz3T0XANLfevVIabHtCO9T5Zr2kHyvpT+0XM9vk44nmsZg==", - "peerDependencies": { - "typestyle": "^2.0.0" - } - }, - "node_modules/csstype": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", - "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/free-style": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/free-style/-/free-style-3.1.0.tgz", - "integrity": "sha512-vJujYSIyT30iDoaoeigNAxX4yB1RUrh+N2ZMhIElMr3BvCuGXOw7XNJMEEJkDUeamK2Rnb/IKFGKRKlTWIGRWA==" - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/ts-node": { - "version": "8.10.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.1.tgz", - "integrity": "sha512-bdNz1L4ekHiJul6SHtZWs1ujEKERJnHs4HxN7rjTyyVOFf3HaJ6sLqe6aPG62XTzAB/63pKRh5jTSWL0D7bsvw==", - "dependencies": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "typescript": ">=2.7" - } - }, - "node_modules/typestyle": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/typestyle/-/typestyle-2.1.0.tgz", - "integrity": "sha512-6uCYPdG4xWLeEcl9O0GtNFnNGhami+irKiLsXSuvWHC/aTS7wdj49WeikWAKN+xHN3b1hm+9v0svwwgSBhCsNA==", - "dependencies": { - "csstype": "2.6.9", - "free-style": "3.1.0" - } - }, - "node_modules/websnacks": { - "resolved": "../..", - "link": true - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "engines": { - "node": ">=6" - } - } - } + "name": "websnacks-example-personal-site", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "websnacks-example-personal-site", + "dependencies": { + "csstips": "^1.2.0", + "ts-node": "^8.10.1", + "typestyle": "^2.1.0", + "websnacks": "../../" + } + }, + "../..": { + "name": "@websnacksjs/websnacks", + "version": "0.2.0", + "license": "MPL-2.0", + "bin": { + "websnacks": "bin/websnacks.js" + }, + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@types/node": "~18", + "@types/ws": "^7.4.0", + "ts-node": "^10.9.2", + "typescript": "~4.9.5" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "node-watch": "^0.7.1", + "ws": "^7.4.3" + } + }, + "../../node_modules/@types/node": { + "version": "12.12.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.38.tgz", + "integrity": "sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==", + "dev": true + }, + "../../node_modules/@types/ws": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.4.tgz", + "integrity": "sha512-9S6Ask71vujkVyeEXKxjBSUV8ZUB0mjL5la4IncBoheu04bDaYyUKErh1BQcY9+WzOUOiKqz/OnpJHYckbMfNg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "../../node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "../../node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "../../node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "../../node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "../../node_modules/node-watch": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.6.4.tgz", + "integrity": "sha512-cI6CHzivIFESe8djiK3Wh90CtWQBxLwMem8x8S+2GSvCvFgoMuOKVlfJtQ/2v3Afg3wOnHl/+tXotEs8z5vOrg==", + "optional": true + }, + "../../node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "../../node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "../../node_modules/ts-node": { + "version": "8.10.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.1.tgz", + "integrity": "sha512-bdNz1L4ekHiJul6SHtZWs1ujEKERJnHs4HxN7rjTyyVOFf3HaJ6sLqe6aPG62XTzAB/63pKRh5jTSWL0D7bsvw==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "../../node_modules/typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + }, + "../../node_modules/ws": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", + "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==", + "optional": true + }, + "../../node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/csstips": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/csstips/-/csstips-1.2.0.tgz", + "integrity": "sha512-2KgBibTljubrEuaiCNdJ0zcy6BmJck+J9YUufb+Hwz3T0XANLfevVIabHtCO9T5Zr2kHyvpT+0XM9vk44nmsZg==", + "peerDependencies": { + "typestyle": "^2.0.0" + } + }, + "node_modules/csstype": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", + "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/free-style": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/free-style/-/free-style-3.1.0.tgz", + "integrity": "sha512-vJujYSIyT30iDoaoeigNAxX4yB1RUrh+N2ZMhIElMr3BvCuGXOw7XNJMEEJkDUeamK2Rnb/IKFGKRKlTWIGRWA==" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/ts-node": { + "version": "8.10.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.1.tgz", + "integrity": "sha512-bdNz1L4ekHiJul6SHtZWs1ujEKERJnHs4HxN7rjTyyVOFf3HaJ6sLqe6aPG62XTzAB/63pKRh5jTSWL0D7bsvw==", + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "node_modules/typescript": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typestyle": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typestyle/-/typestyle-2.1.0.tgz", + "integrity": "sha512-6uCYPdG4xWLeEcl9O0GtNFnNGhami+irKiLsXSuvWHC/aTS7wdj49WeikWAKN+xHN3b1hm+9v0svwwgSBhCsNA==", + "dependencies": { + "csstype": "2.6.9", + "free-style": "3.1.0" + } + }, + "node_modules/websnacks": { + "resolved": "../..", + "link": true + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + } + } } diff --git a/examples/personal-site/package.json b/examples/personal-site/package.json index 471d1cb..c703985 100644 --- a/examples/personal-site/package.json +++ b/examples/personal-site/package.json @@ -1,13 +1,14 @@ { - "name": "websnacks-example-personal-site", - "scripts": { - "build": "websnacks -r ts-node/register build", - "dev": "websnacks -r ts-node/register dev" - }, - "dependencies": { - "csstips": "^1.2.0", - "ts-node": "^8.10.1", - "typestyle": "^2.1.0", - "websnacks": "../../" - } + "name": "websnacks-example-personal-site", + "type": "module", + "scripts": { + "build": "websnacks -r ts-node/register build", + "dev": "websnacks -r ts-node/register dev" + }, + "dependencies": { + "csstips": "^1.2.0", + "ts-node": "^8.10.1", + "typestyle": "^2.1.0", + "websnacks": "../../" + } } diff --git a/examples/personal-site/pages/index.tsx b/examples/personal-site/pages/index.tsx index d94ed6f..1c4393e 100644 --- a/examples/personal-site/pages/index.tsx +++ b/examples/personal-site/pages/index.tsx @@ -1,22 +1,21 @@ -import { Component, createElement } from "websnacks"; +import { type Component, createElement } from "websnacks"; import { Layout } from "../components/layout"; export const page: Component = () => ( - -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur - dapibus condimentum mauris et egestas. Quisque orci nulla, consequat - at erat laoreet, malesuada sodales nisi. Sed in lorem semper lorem - placerat fermentum a id arcu. Curabitur non aliquam tellus, sed - auctor lacus. Nunc sit amet lectus ultrices, sodales nisl sit amet, - luctus nisl. Nunc mollis imperdiet quam, eget sollicitudin leo - tincidunt vel. Duis felis dui, imperdiet aliquam bibendum sed, - auctor et dolor. Vivamus odio ipsum, venenatis in felis sed, aliquam - dictum turpis. Pellentesque pellentesque consequat neque, id - imperdiet diam molestie nec. Nullam ut vestibulum est. Pellentesque - orci urna, porta vel porta quis, semper ut enim. Donec sit amet urna - arcu. Nam tincidunt fermentum ligula a pharetra.{" "} -

-
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur dapibus + condimentum mauris et egestas. Quisque orci nulla, consequat at erat + laoreet, malesuada sodales nisi. Sed in lorem semper lorem placerat + fermentum a id arcu. Curabitur non aliquam tellus, sed auctor lacus. Nunc + sit amet lectus ultrices, sodales nisl sit amet, luctus nisl. Nunc mollis + imperdiet quam, eget sollicitudin leo tincidunt vel. Duis felis dui, + imperdiet aliquam bibendum sed, auctor et dolor. Vivamus odio ipsum, + venenatis in felis sed, aliquam dictum turpis. Pellentesque pellentesque + consequat neque, id imperdiet diam molestie nec. Nullam ut vestibulum est. + Pellentesque orci urna, porta vel porta quis, semper ut enim. Donec sit + amet urna arcu. Nam tincidunt fermentum ligula a pharetra.{" "} +

+
); diff --git a/examples/personal-site/pages/projects.tsx b/examples/personal-site/pages/projects.tsx index 0586649..5b2c133 100644 --- a/examples/personal-site/pages/projects.tsx +++ b/examples/personal-site/pages/projects.tsx @@ -1,26 +1,26 @@ import { stylesheet } from "typestyle"; -import { Component, createElement } from "websnacks"; +import { type Component, createElement } from "websnacks"; import { Layout } from "../components/layout"; const styles = stylesheet({ - projectsGrid: { - display: "flex", - flexWrap: "wrap", - width: "25%", - }, + projectsGrid: { + display: "flex", + flexWrap: "wrap", + width: "25%", + }, }); export const page: Component = () => ( - -

Projects

+ +

Projects

-
-
Project 1
-
Project 2
-
Project 3
-
Project 4
-
Project 5
-
-
+
+
Project 1
+
Project 2
+
Project 3
+
Project 4
+
Project 5
+
+
); diff --git a/examples/personal-site/tsconfig.json b/examples/personal-site/tsconfig.json index 1cfeaeb..4c31835 100644 --- a/examples/personal-site/tsconfig.json +++ b/examples/personal-site/tsconfig.json @@ -1,17 +1,17 @@ { - "compilerOptions": { - "esModuleInterop": true, - "module": "CommonJS", - "moduleResolution": "node", - "jsx": "react", - "jsxFactory": "createElement", - "target": "ES2018", - "lib": ["ES2018"], - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["components/**/*", "pages/**/*"] + "compilerOptions": { + "esModuleInterop": true, + "module": "CommonJS", + "moduleResolution": "node", + "jsx": "react", + "jsxFactory": "createElement", + "target": "ES2018", + "lib": ["ES2018"], + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["components/**/*", "pages/**/*"] } diff --git a/examples/personal-site/websnacks.ts b/examples/personal-site/websnacks.ts index 77dbf34..ce3b7b9 100644 --- a/examples/personal-site/websnacks.ts +++ b/examples/personal-site/websnacks.ts @@ -1,26 +1,25 @@ -import { promises as fs } from "fs"; -import * as path from "path"; -import { Config } from "websnacks"; +import { promises as fs } from "node:fs"; +import * as path from "node:path"; +import type { Config } from "websnacks"; import { stylesheetPath } from "./config"; const config: Config = { - // Watch additional files and folders for changes when the dev server is - // running. - watch: ["components/", "config.ts"], - // Hooks to execute after certain rendering events. Currently only - // afterSiteRender is supported. - hooks: { - async afterSiteRender({ outDir }): Promise { - // NOTE: we dynamically import typestyle so that the global style - // registry is properly updated once all pages are reloaded in - // dev. We could also create a typestyle object in config.ts, - // or even multiple objects to split up our styles into e.g. a - // critical-path.css and noncrticial.css. - const { getStyles } = await import("typestyle"); - const styles = getStyles(); - await fs.writeFile(path.join(outDir, stylesheetPath), styles); - }, - }, + // Watch additional files and folders for changes when the dev server is + // running. + watch: ["components/", "config.ts"], + // Hooks to execute after certain rendering events. Currently only + // afterSiteRender is supported. + hooks: { + async afterSiteRender({ outDir }): Promise { + // NOTE: we dynamically import typestyle so that the global style + // registry is properly updated once all pages are reloaded in + // dev. We could also create a typestyle object in config.ts, + // or even multiple objects to split up our styles into e.g. a + // critical-path.css and noncrticial.css. + const { getStyles } = await import("typestyle"); + const styles = getStyles(); + await fs.writeFile(path.join(outDir, stylesheetPath), styles); + }, + }, }; -export = config; diff --git a/package-lock.json b/package-lock.json index 126d696..228d42b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,15 +12,9 @@ "websnacks": "bin/websnacks.js" }, "devDependencies": { + "@biomejs/biome": "1.8.3", "@types/node": "~18", "@types/ws": "^7.4.0", - "@typescript-eslint/eslint-plugin": "^4.15.2", - "@typescript-eslint/parser": "^4.15.2", - "eslint": "^7.21.0", - "eslint-config-prettier": "^8.1.0", - "eslint-plugin-prettier": "^3.3.1", - "eslint-plugin-react": "^7.22.0", - "prettier": "=2.2.1", "ts-node": "^10.9.2", "typescript": "~4.9.5" }, @@ -32,44 +26,159 @@ "ws": "^7.4.3" } }, - "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==", + "node_modules/@biomejs/biome": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.3.tgz", + "integrity": "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==", "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" + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" }, "engines": { - "node": ">=4" + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.8.3", + "@biomejs/cli-darwin-x64": "1.8.3", + "@biomejs/cli-linux-arm64": "1.8.3", + "@biomejs/cli-linux-arm64-musl": "1.8.3", + "@biomejs/cli-linux-x64": "1.8.3", + "@biomejs/cli-linux-x64-musl": "1.8.3", + "@biomejs/cli-win32-arm64": "1.8.3", + "@biomejs/cli-win32-x64": "1.8.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.3.tgz", + "integrity": "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.3.tgz", + "integrity": "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.3.tgz", + "integrity": "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.3.tgz", + "integrity": "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.3.tgz", + "integrity": "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.3.tgz", + "integrity": "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.3.tgz", + "integrity": "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz", + "integrity": "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" } }, "node_modules/@cspotcode/source-map-support": { @@ -84,35 +193,6 @@ "node": ">=12" } }, - "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/@eslint/eslintrc/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/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -138,41 +218,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "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/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -197,12 +242,6 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, - "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": "18.19.39", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", @@ -221,184 +260,6 @@ "@types/node": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz", - "integrity": "sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.15.2", - "@typescript-eslint/scope-manager": "4.15.2", - "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.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz", - "integrity": "sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.15.2", - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/typescript-estree": "4.15.2", - "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.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.2.tgz", - "integrity": "sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.15.2", - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/typescript-estree": "4.15.2", - "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.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz", - "integrity": "sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2" - }, - "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.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.2.tgz", - "integrity": "sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ==", - "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.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz", - "integrity": "sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2", - "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.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz", - "integrity": "sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.15.2", - "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/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/acorn-walk": { "version": "8.3.3", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", @@ -423,318 +284,18 @@ "node": ">=0.4.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/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "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-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/array.prototype.flatmap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", - "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "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.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "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/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -744,943 +305,12 @@ "node": ">=0.3.1" } }, - "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/es-abstract": { - "version": "1.18.0-next.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", - "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.1", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.3", - "string.prototype.trimstart": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-config-prettier": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.1.0.tgz", - "integrity": "sha512-oKMhGv3ihGbCIimCAjqkdzx2Q+jthoqnXSP+d86M9tptwugycmTFdVR4IpLgq2c4SHifbwO90z2fQ8/Aio73yw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", - "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", - "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "resolve": "^1.18.1", - "string.prototype.matchall": "^4.0.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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-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-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-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/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/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.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/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/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-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "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/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "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/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "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/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "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/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/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=", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "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/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/jsx-ast-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", - "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.2", - "object.assign": "^4.1.2" - }, - "engines": { - "node": ">=4.0" - } - }, - "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/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "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/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "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/node-watch": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.1.tgz", @@ -1690,645 +320,6 @@ "node": ">=6" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", - "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", - "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "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/prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.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/prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - }, - "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/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "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/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/string.prototype.matchall": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz", - "integrity": "sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.3.1", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -2384,48 +375,6 @@ "node": ">=0.4.0" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "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.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -2445,57 +394,12 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "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/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "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/ws": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", @@ -2517,12 +421,6 @@ } } }, - "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 - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 0055008..6f864c5 100644 --- a/package.json +++ b/package.json @@ -1,54 +1,49 @@ { - "name": "@websnacksjs/websnacks", - "description": "Minimal dependency server-side JSX for static sites", - "version": "0.2.0", - "author": { - "name": "M. George Hansen", - "email": "mgeorge@technopolitica.com" - }, - "license": "MPL-2.0", - "repository": "github:websnacksjs/websnacks", - "engines": { - "node": ">=18" - }, - "main": "dist/index.js", - "types": "types.d.ts", - "bin": "bin/websnacks.js", - "files": [ - "/bin/websnacks.js", - "/dist/**/*.js", - "/dist/**/*.d.ts", - "/dist/**/*.map", - "/src/**/*.ts", - "/index.d.ts" - ], - "scripts": { - "build": "tsc", - "clean": "ts-node scripts/clean.ts", - "prepublishOnly": "npm run reset && npm test", - "pretest": "npm run build", - "preversion": "npm run reset && npm test", - "release": "npm version", - "reset": "npm run clean && npm ci", - "test": "npm run test:unit && npm run test:e2e", - "test:unit": "cd test && ts-node --script-mode ./run-tests.ts", - "test:e2e": "cd test && ts-node --script-mode ./run-e2e.ts" - }, - "devDependencies": { - "@types/node": "~18", - "@types/ws": "^7.4.0", - "@typescript-eslint/eslint-plugin": "^4.15.2", - "@typescript-eslint/parser": "^4.15.2", - "eslint": "^7.21.0", - "eslint-config-prettier": "^8.1.0", - "eslint-plugin-prettier": "^3.3.1", - "eslint-plugin-react": "^7.22.0", - "prettier": "=2.2.1", - "ts-node": "^10.9.2", - "typescript": "~4.9.5" - }, - "optionalDependencies": { - "node-watch": "^0.7.1", - "ws": "^7.4.3" - } + "name": "@websnacksjs/websnacks", + "description": "Minimal dependency server-side JSX for static sites", + "version": "0.2.0", + "author": { + "name": "M. George Hansen", + "email": "mgeorge@technopolitica.com" + }, + "license": "MPL-2.0", + "repository": "github:websnacksjs/websnacks", + "engines": { + "node": ">=18" + }, + "main": "dist/index.js", + "types": "types.d.ts", + "bin": "bin/websnacks.js", + "files": [ + "/bin/websnacks.js", + "/dist/**/*.js", + "/dist/**/*.d.ts", + "/dist/**/*.map", + "/src/**/*.ts", + "/index.d.ts" + ], + "scripts": { + "build": "tsc", + "check": "biome check .", + "clean": "ts-node scripts/clean.ts", + "prepublishOnly": "npm run reset && npm test", + "pretest": "npm run build", + "preversion": "npm run reset && npm test", + "release": "npm version", + "reset": "npm run clean && npm ci", + "test": "npm run test:unit && npm run test:e2e", + "test:unit": "cd test && ts-node --script-mode ./run-tests.ts", + "test:e2e": "cd test && ts-node --script-mode ./run-e2e.ts" + }, + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@types/node": "~18", + "@types/ws": "^7.4.0", + "ts-node": "^10.9.2", + "typescript": "~4.9.5" + }, + "optionalDependencies": { + "node-watch": "^0.7.1", + "ws": "^7.4.3" + } } diff --git a/scripts/clean.ts b/scripts/clean.ts index 5eaec83..e606197 100644 --- a/scripts/clean.ts +++ b/scripts/clean.ts @@ -3,28 +3,28 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import * as fs from "fs"; -import * as path from "path"; +import * as fs from "node:fs"; +import * as path from "node:path"; const ROOT_DIR = path.resolve(__dirname, ".."); const DIST_DIR = path.join(ROOT_DIR, "dist"); const TEST_DIR = path.join(ROOT_DIR, ".temp"); const rmdirRecursive = (dirPath: string): void => { - if (!fs.existsSync(dirPath)) { - return; - } - const entryNames = fs.readdirSync(dirPath); - for (const entryName of entryNames) { - const entryPath = path.join(dirPath, entryName); - const dirent = fs.lstatSync(entryPath); - if (dirent.isDirectory()) { - rmdirRecursive(entryPath); - } else { - fs.unlinkSync(entryPath); - } - } - fs.rmdirSync(dirPath); + if (!fs.existsSync(dirPath)) { + return; + } + const entryNames = fs.readdirSync(dirPath); + for (const entryName of entryNames) { + const entryPath = path.join(dirPath, entryName); + const dirent = fs.lstatSync(entryPath); + if (dirent.isDirectory()) { + rmdirRecursive(entryPath); + } else { + fs.unlinkSync(entryPath); + } + } + fs.rmdirSync(dirPath); }; rmdirRecursive(DIST_DIR); diff --git a/src/build.ts b/src/build.ts index a3c5c22..c564ac6 100644 --- a/src/build.ts +++ b/src/build.ts @@ -3,78 +3,78 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { promises as fs } from "fs"; -import * as path from "path"; +import { promises as fs } from "node:fs"; +import * as path from "node:path"; -import { Config, ConfigPaths } from "./config"; +import type { Config, ConfigPaths } from "./config"; import { renderPage } from "./render"; import { decacheModule, walkDir } from "./utils"; const renderPagesToHtml = async ({ - pagesDir, - outDir, + pagesDir, + outDir, }: ConfigPaths): Promise => { - const deferred = []; - for await (const srcPath of walkDir(pagesDir)) { - const ext = path.extname(srcPath); - if (ext !== ".tsx") { - continue; - } + const deferred = []; + for await (const srcPath of walkDir(pagesDir)) { + const ext = path.extname(srcPath); + if (ext !== ".tsx") { + continue; + } - // Ensure that we don't cache page modules when running in dev server. - decacheModule(srcPath); - // eslint-disable-next-line @typescript-eslint/no-var-requires - const pageSrc = require(srcPath); - if (!("page" in pageSrc)) { - throw new Error( - `page source at ${srcPath} does not export a "page" variable`, - ); - } - let compiledHtml; - try { - compiledHtml = renderPage(pageSrc.page()); - } catch (error) { - throw new Error(`failed to compile ${srcPath}: ${error}`); - } - const relPath = path.relative(pagesDir, path.dirname(srcPath)); - let baseName = path.basename(srcPath, ".tsx"); - if (baseName === "index") { - baseName = ""; - } - const destPath = path.join(outDir, relPath, baseName, "index.html"); - deferred.push( - (async () => { - await fs.mkdir(path.dirname(destPath), { recursive: true }); - await fs.writeFile(destPath, compiledHtml); - })(), - ); - } - await Promise.all(deferred); + // Ensure that we don't cache page modules when running in dev server. + decacheModule(srcPath); + // eslint-disable-next-line @typescript-eslint/no-var-requires + const pageSrc = require(srcPath); + if (!("page" in pageSrc)) { + throw new Error( + `page source at ${srcPath} does not export a "page" variable`, + ); + } + let compiledHtml: string; + try { + compiledHtml = renderPage(pageSrc.page()); + } catch (error) { + throw new Error(`failed to compile ${srcPath}: ${error}`); + } + const relPath = path.relative(pagesDir, path.dirname(srcPath)); + let baseName = path.basename(srcPath, ".tsx"); + if (baseName === "index") { + baseName = ""; + } + const destPath = path.join(outDir, relPath, baseName, "index.html"); + deferred.push( + (async () => { + await fs.mkdir(path.dirname(destPath), { recursive: true }); + await fs.writeFile(destPath, compiledHtml); + })(), + ); + } + await Promise.all(deferred); }; const copyStaticAssets = async ({ - staticAssetsDir, - outDir, + staticAssetsDir, + outDir, }: ConfigPaths): Promise => { - try { - await fs.access(staticAssetsDir); - } catch (error) { - // Static assets folder doesn't exist, so no-op. - return; - } + try { + await fs.access(staticAssetsDir); + } catch (error) { + // Static assets folder doesn't exist, so no-op. + return; + } - const deferred = []; - for await (const assetPath of walkDir(staticAssetsDir)) { - const relPath = path.relative(staticAssetsDir, assetPath); - const destPath = path.join(outDir, relPath); - deferred.push( - (async () => { - await fs.mkdir(path.dirname(destPath), { recursive: true }); - await fs.copyFile(assetPath, destPath); - })(), - ); - } - await Promise.all(deferred); + const deferred = []; + for await (const assetPath of walkDir(staticAssetsDir)) { + const relPath = path.relative(staticAssetsDir, assetPath); + const destPath = path.join(outDir, relPath); + deferred.push( + (async () => { + await fs.mkdir(path.dirname(destPath), { recursive: true }); + await fs.copyFile(assetPath, destPath); + })(), + ); + } + await Promise.all(deferred); }; /** @@ -84,6 +84,6 @@ const copyStaticAssets = async ({ * @param config Configuration for the site. */ export const renderSite = async ({ paths, hooks }: Config): Promise => { - await Promise.all([renderPagesToHtml(paths), copyStaticAssets(paths)]); - await hooks.afterSiteRender(paths); + await Promise.all([renderPagesToHtml(paths), copyStaticAssets(paths)]); + await hooks.afterSiteRender(paths); }; diff --git a/src/cli/commands/build.ts b/src/cli/commands/build.ts index 7c14947..1dc94fc 100644 --- a/src/cli/commands/build.ts +++ b/src/cli/commands/build.ts @@ -5,7 +5,7 @@ import { renderSite } from "../../build"; import { loadConfig } from "../../config"; -import { Command, UsageError } from "../types"; +import { type Command, UsageError } from "../types"; const helpText = `\ Usage: websnacks build [ROOT_DIR] @@ -18,16 +18,16 @@ Args: `; interface BuildArgs { - rootDir: string; + rootDir: string; } const parseArgs = (args: string[]): BuildArgs => { - if (args.length > 1) { - throw new UsageError("too many arguments provided", helpText); - } - return { - rootDir: args[0] || process.cwd(), - }; + if (args.length > 1) { + throw new UsageError("too many arguments provided", helpText); + } + return { + rootDir: args[0] || process.cwd(), + }; }; /** @@ -35,11 +35,11 @@ const parseArgs = (args: string[]): BuildArgs => { * static files. */ const buildCommand: Command = { - execute: async (args: string[]): Promise => { - const { rootDir } = parseArgs(args); - const config = await loadConfig(rootDir); - await renderSite(config); - }, - helpText, + execute: async (args: string[]): Promise => { + const { rootDir } = parseArgs(args); + const config = await loadConfig(rootDir); + await renderSite(config); + }, + helpText, }; export = buildCommand; diff --git a/src/cli/commands/dev.ts b/src/cli/commands/dev.ts index 28dc410..b5c1d53 100644 --- a/src/cli/commands/dev.ts +++ b/src/cli/commands/dev.ts @@ -3,21 +3,21 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { existsSync, promises as fs, watch } from "fs"; -import * as http from "http"; -import * as path from "path"; +import { promises as fs, existsSync, watch } from "node:fs"; +import * as http from "node:http"; +import * as path from "node:path"; import { renderSite } from "../../build"; -import { Config, loadConfig } from "../../config"; +import { type Config, loadConfig } from "../../config"; import { isErrnoException } from "../../utils/error"; -import { Command, UsageError } from "../types"; +import { type Command, UsageError } from "../types"; const DEFAULT_SERVER_PORT = 8080; const injectLiveReloadScript = (htmlContents: string, port: number): string => - htmlContents.replace( - "", - ` + htmlContents.replace( + "", + ` `, - ); + ); const guessMimeType = (ext: string): string => { - let mimeType; - switch (ext) { - case ".apng": - mimeType = "image/apng"; - break; - case ".bmp": - mimeType = "image/bmp"; - break; - case ".css": - mimeType = "text/css"; - break; - case ".eot": - mimeType = "application/vnd.ms-fontobject"; - break; - case ".gif": - mimeType = "image/gif"; - break; - case ".htm": - case ".html": - mimeType = "text/html"; - break; - case ".ico": - mimeType = "image/vnd.microsoft.icon"; - break; - case ".jpg": - case ".jpeg": - mimeType = "image/jpeg"; - break; - case ".js": - case ".mjs": - mimeType = "text/javascript"; - break; - case ".mp3": - mimeType = "audio/mpeg"; - break; - case ".mpeg": - mimeType = "video/mpeg"; - break; - case ".oga": - mimeType = "audio/ogg"; - break; - case ".ogv": - mimeType = "video/ogg"; - break; - case ".otf": - mimeType = "font/otf"; - break; - case ".png": - mimeType = "image/png"; - break; - case ".svg": - mimeType = "image/svg+xml"; - break; - case ".txt": - mimeType = "text/plain"; - break; - case ".tif": - case ".tiff": - mimeType = "image/tiff"; - break; - case ".ttf": - mimeType = "font/ttf"; - break; - case ".wav": - mimeType = "audio/wav"; - break; - case ".weba": - mimeType = "audio/webm"; - break; - case ".webm": - mimeType = "video/webm"; - break; - case ".webp": - mimeType = "image/webp"; - break; - case ".woff": - mimeType = "font/woff"; - break; - case ".woff2": - mimeType = "font/woff2"; - break; - default: - // Default to binary mimetype which most browsers will be able to - // correctly interpret in the right context. - mimeType = "application/octet-stream"; - } - return mimeType; + let mimeType: string; + switch (ext) { + case ".apng": + mimeType = "image/apng"; + break; + case ".bmp": + mimeType = "image/bmp"; + break; + case ".css": + mimeType = "text/css"; + break; + case ".eot": + mimeType = "application/vnd.ms-fontobject"; + break; + case ".gif": + mimeType = "image/gif"; + break; + case ".htm": + case ".html": + mimeType = "text/html"; + break; + case ".ico": + mimeType = "image/vnd.microsoft.icon"; + break; + case ".jpg": + case ".jpeg": + mimeType = "image/jpeg"; + break; + case ".js": + case ".mjs": + mimeType = "text/javascript"; + break; + case ".mp3": + mimeType = "audio/mpeg"; + break; + case ".mpeg": + mimeType = "video/mpeg"; + break; + case ".oga": + mimeType = "audio/ogg"; + break; + case ".ogv": + mimeType = "video/ogg"; + break; + case ".otf": + mimeType = "font/otf"; + break; + case ".png": + mimeType = "image/png"; + break; + case ".svg": + mimeType = "image/svg+xml"; + break; + case ".txt": + mimeType = "text/plain"; + break; + case ".tif": + case ".tiff": + mimeType = "image/tiff"; + break; + case ".ttf": + mimeType = "font/ttf"; + break; + case ".wav": + mimeType = "audio/wav"; + break; + case ".weba": + mimeType = "audio/webm"; + break; + case ".webm": + mimeType = "video/webm"; + break; + case ".webp": + mimeType = "image/webp"; + break; + case ".woff": + mimeType = "font/woff"; + break; + case ".woff2": + mimeType = "font/woff2"; + break; + default: + // Default to binary mimetype which most browsers will be able to + // correctly interpret in the right context. + mimeType = "application/octet-stream"; + } + return mimeType; }; const portFromServer = ( - addrInfo: { port: number } | object | string | undefined | null, + addrInfo: { port: number } | object | string | undefined | null, ): number => { - if ( - typeof addrInfo !== "object" || - addrInfo == null || - !("port" in addrInfo) - ) { - throw new Error( - "server address does not have a valid port (this should never happen!)", - ); - } - return addrInfo.port; + if ( + typeof addrInfo !== "object" || + addrInfo == null || + !("port" in addrInfo) + ) { + throw new Error( + "server address does not have a valid port (this should never happen!)", + ); + } + return addrInfo.port; }; const startHttpServer = async (publicDir: string): Promise => { - const httpServer = http.createServer(async (req, res) => { - if (req.url == null) { - res.writeHead(404); - res.end(); - return; - } + const httpServer = http.createServer(async (req, res) => { + if (req.url == null) { + res.writeHead(404); + res.end(); + return; + } - let reqExt = path.extname(req.url); - let reqPath = req.url; - if (!reqExt) { - reqPath = path.join(reqPath, "index.html"); - reqExt = ".html"; - } + let reqExt = path.extname(req.url); + let reqPath = req.url; + if (!reqExt) { + reqPath = path.join(reqPath, "index.html"); + reqExt = ".html"; + } - let contents; - try { - contents = await fs.readFile(path.join(publicDir, reqPath)); - } catch (error) { - console.error(`unable to load file ${reqPath}`); - res.writeHead(404); - res.end(); - return; - } - const mimeType = guessMimeType(reqExt); - if (mimeType === "text/html") { - const port = portFromServer(req.socket.address()); - contents = injectLiveReloadScript(contents.toString("utf8"), port); - } - res.writeHead(200, { - "Content-Type": mimeType, - }); - res.end(contents); - }); - const listen = async (port?: number): Promise => - new Promise((resolve, reject) => { - httpServer - .once("error", (error) => reject(error)) - .once("listening", () => resolve()) - .listen(port); - }); - try { - await listen(DEFAULT_SERVER_PORT); - } catch (error) { - if ( - error instanceof Error && - isErrnoException(error) && - error.code !== "EADDRINUSE" - ) { - throw error; - } - await listen(); - } - const port = portFromServer(httpServer.address()); - console.log(`Listening at http://127.0.0.1:${port}`); - return httpServer; + let contents: Buffer | string; + try { + contents = await fs.readFile(path.join(publicDir, reqPath)); + } catch (error) { + console.error(`unable to load file ${reqPath}`); + res.writeHead(404); + res.end(); + return; + } + const mimeType = guessMimeType(reqExt); + if (mimeType === "text/html") { + const port = portFromServer(req.socket.address()); + contents = injectLiveReloadScript(contents.toString("utf8"), port); + } + res.writeHead(200, { + "Content-Type": mimeType, + }); + res.end(contents); + }); + const listen = async (port?: number): Promise => + new Promise((resolve, reject) => { + httpServer + .once("error", (error) => reject(error)) + .once("listening", () => resolve()) + .listen(port); + }); + try { + await listen(DEFAULT_SERVER_PORT); + } catch (error) { + if ( + error instanceof Error && + isErrnoException(error) && + error.code !== "EADDRINUSE" + ) { + throw error; + } + await listen(); + } + const port = portFromServer(httpServer.address()); + console.log(`Listening at http://127.0.0.1:${port}`); + return httpServer; }; const startWebSocketServer = async ( - httpServer: http.Server, + httpServer: http.Server, ): Promise => { - // Attempt to load the ws module, aborting if it isn't available. - let ws; - try { - ws = await import("ws"); - } catch (error) { - if ( - error instanceof Error && - isErrnoException(error) && - error.code !== "MODULE_NOT_FOUND" - ) { - throw error; - } - console.warn(`'ws' module not found, live-reloading will be disabled`); - return; - } - const wsServer = new ws.Server({ server: httpServer }); - wsServer.on("connection", () => { - console.log("connected to dev site"); - }); - return wsServer; + // Attempt to load the ws module, aborting if it isn't available. + let ws: typeof import("ws"); + try { + ws = await import("ws"); + } catch (error) { + if ( + error instanceof Error && + isErrnoException(error) && + error.code !== "MODULE_NOT_FOUND" + ) { + throw error; + } + console.warn(`'ws' module not found, live-reloading will be disabled`); + return; + } + const wsServer = new ws.Server({ server: httpServer }); + wsServer.on("connection", () => { + console.log("connected to dev site"); + }); + return wsServer; }; const watchFolders = async ( - folders: string[], - listener: (eventType?: "update" | "remove", fileName?: string) => void, + folders: string[], + listener: (eventType?: "update" | "remove", fileName?: string) => void, ): Promise => { - // Try to load node-watch, falling back to fs watch if node-watch isn't - // available. - try { - const nodeWatch = await import("node-watch"); - nodeWatch.default(folders, { recursive: true }, listener); - return; - } catch (error) { - if ( - error instanceof Error && - isErrnoException(error) && - error.code !== "MODULE_NOT_FOUND" - ) { - throw error; - } - console.warn( - `'node-watch' module not found, falling back to fs.watch (may ` + - `result in file watch issues on some OSes)`, - ); - } - // NOTE: fs.watch has significant cross-platform issues, including - // triggering duplicate file events on some systems. - for (const folder of folders) { - watch(folder, { recursive: true }, (_, fileName) => { - listener("update", fileName || undefined); - }); - } + // Try to load node-watch, falling back to fs watch if node-watch isn't + // available. + try { + const nodeWatch = await import("node-watch"); + nodeWatch.default(folders, { recursive: true }, listener); + return; + } catch (error) { + if ( + error instanceof Error && + isErrnoException(error) && + error.code !== "MODULE_NOT_FOUND" + ) { + throw error; + } + console.warn( + `'node-watch' module not found, falling back to fs.watch (may ` + + "result in file watch issues on some OSes)", + ); + } + // NOTE: fs.watch has significant cross-platform issues, including + // triggering duplicate file events on some systems. + for (const folder of folders) { + watch(folder, { recursive: true }, (_, fileName) => { + listener("update", fileName || undefined); + }); + } }; const helpText = `\ @@ -259,16 +259,16 @@ Args: `; interface DevArgs { - rootDir: string; + rootDir: string; } const parseArgs = (args: string[]): DevArgs | null => { - if (args.length > 1) { - throw new UsageError("too many arguments provided", helpText); - } - return { - rootDir: args[0] || process.cwd(), - }; + if (args.length > 1) { + throw new UsageError("too many arguments provided", helpText); + } + return { + rootDir: args[0] || process.cwd(), + }; }; /** @@ -277,39 +277,37 @@ const parseArgs = (args: string[]): DevArgs | null => { * production static hosting environment as closely as possible. */ const devCommand: Command = { - async execute(args: string[]): Promise { - const parsedArgs = parseArgs(args); - if (!parsedArgs) { - return; - } - const { rootDir } = parsedArgs; - const rebuild = async (): Promise => { - const config = await loadConfig(rootDir); - await renderSite(config); - return config; - }; - const config = await rebuild(); - const { outDir } = config.paths; - const httpServer = await startHttpServer(outDir); - const wsServer = await startWebSocketServer(httpServer); - const watchedFolders = config.watch.filter((filePath) => - existsSync(filePath), - ); - await watchFolders(watchedFolders, async (event, filePath) => { - const filePathForLog = filePath || ""; - const eventForLog = event || ""; - console.log( - `${filePathForLog}:${eventForLog} triggering rebuild...`, - ); - await rebuild(); - if (wsServer != null) { - console.log(`rebuild finished, reloading browsers...`); - for (const ws of wsServer.clients) { - ws.send("reload"); - } - } - }); - }, - helpText, + async execute(args: string[]): Promise { + const parsedArgs = parseArgs(args); + if (!parsedArgs) { + return; + } + const { rootDir } = parsedArgs; + const rebuild = async (): Promise => { + const config = await loadConfig(rootDir); + await renderSite(config); + return config; + }; + const config = await rebuild(); + const { outDir } = config.paths; + const httpServer = await startHttpServer(outDir); + const wsServer = await startWebSocketServer(httpServer); + const watchedFolders = config.watch.filter((filePath) => + existsSync(filePath), + ); + await watchFolders(watchedFolders, async (event, filePath) => { + const filePathForLog = filePath || ""; + const eventForLog = event || ""; + console.log(`${filePathForLog}:${eventForLog} triggering rebuild...`); + await rebuild(); + if (wsServer != null) { + console.log("rebuild finished, reloading browsers..."); + for (const ws of wsServer.clients) { + ws.send("reload"); + } + } + }); + }, + helpText, }; export = devCommand; diff --git a/src/cli/index.ts b/src/cli/index.ts index 3d198ef..79317e6 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { Command, UsageError } from "./types"; +import { type Command, UsageError } from "./types"; const globalHelpText = `\ Usage: websnacks [...globalOptions] @@ -19,97 +19,94 @@ Commands: `; interface Options { - showHelp: boolean; - require: string[]; + showHelp: boolean; + require: string[]; } const parseArgs = ( - args: string[], + args: string[], ): { options: Options; commandName?: string; commandArgs: string[] } => { - const options: Options = { - showHelp: false, - require: [], - }; - // Look ahead for the first argument that doesn't start with a "-" to - // indicate the end of option parsing. - while (args.length > 0 && args[0].indexOf("-") >= 0) { - const opt = args.shift(); - switch (opt) { - case "-h": - case "--help": { - options.showHelp = true; - break; - } - case "-r": - case "--require": { - const moduleName = args.shift(); - if (moduleName == null) { - throw new UsageError( - `-r requires a valid module name`, - globalHelpText, - ); - } - options.require.push(moduleName); - break; - } - default: - throw new UsageError(`unknown option ${opt}`, globalHelpText); - } - } - const commandName = args.shift(); - return { options, commandName, commandArgs: args }; + const options: Options = { + showHelp: false, + require: [], + }; + // Look ahead for the first argument that doesn't start with a "-" to + // indicate the end of option parsing. + while (args.length > 0 && args[0].indexOf("-") >= 0) { + const opt = args.shift(); + switch (opt) { + case "-h": + case "--help": { + options.showHelp = true; + break; + } + case "-r": + case "--require": { + const moduleName = args.shift(); + if (moduleName == null) { + throw new UsageError( + "-r requires a valid module name", + globalHelpText, + ); + } + options.require.push(moduleName); + break; + } + default: + throw new UsageError(`unknown option ${opt}`, globalHelpText); + } + } + const commandName = args.shift(); + return { options, commandName, commandArgs: args }; }; const _main = async (args: string[]): Promise => { - const { options, commandName, commandArgs } = parseArgs(args); - if (options.showHelp) { - console.log(`${globalHelpText}\n`); - return; - } - if (commandName == null) { - throw new UsageError(`must specify a valid command`, globalHelpText); - } - for (const moduleName of options.require) { - await import(moduleName); - } + const { options, commandName, commandArgs } = parseArgs(args); + if (options.showHelp) { + console.log(`${globalHelpText}\n`); + return; + } + if (commandName == null) { + throw new UsageError("must specify a valid command", globalHelpText); + } + for (const moduleName of options.require) { + await import(moduleName); + } - let command: Command; - switch (commandName) { - case "build": - command = await import("./commands/build"); - break; - case "dev": - command = await import("./commands/dev"); - break; - default: - throw new UsageError( - `unknown command ${commandName}`, - globalHelpText, - ); - } - // NOTE: Should this just delegate to the command? - for (const arg of commandArgs) { - if (arg === "--help" || arg === "-h") { - console.log(`${command.helpText}\n`); - return; - } - } - await command.execute(commandArgs); + let command: Command; + switch (commandName) { + case "build": + command = await import("./commands/build"); + break; + case "dev": + command = await import("./commands/dev"); + break; + default: + throw new UsageError(`unknown command ${commandName}`, globalHelpText); + } + // NOTE: Should this just delegate to the command? + for (const arg of commandArgs) { + if (arg === "--help" || arg === "-h") { + console.log(`${command.helpText}\n`); + return; + } + } + await command.execute(commandArgs); }; /** * Entrypoint of the CLI app. */ export const main = (): void => { - _main(process.argv.slice(2)).catch((error) => { - if (error instanceof UsageError) { - console.error(`Error: ${error.message}\n`); - console.log(`${error.helpText}\n`); - } else { - const errorMsg = - error instanceof Error ? error.stack : JSON.stringify(error); - console.error(`Unexpected error: ${errorMsg}\n`); - } - process.exit(1); - }); + _main(process.argv.slice(2)).catch((error) => { + if (error instanceof UsageError) { + console.error(`Error: ${error.message}\n`); + console.log(`${error.helpText}\n`); + } else { + const errorMsg = + error instanceof Error ? error.stack : JSON.stringify(error); + console.error(`Unexpected error: ${errorMsg}\n`); + } + process.exit(1); + }); }; diff --git a/src/cli/types.ts b/src/cli/types.ts index 26234e9..6b9656b 100644 --- a/src/cli/types.ts +++ b/src/cli/types.ts @@ -7,16 +7,16 @@ * CLI command representing an action that the CLI program supports. */ export interface Command { - /** - * Execute the command with the specified arguments. - * - * @param args List of CLI arguments to pass to the command. - */ - execute(args: string[]): Promise; - /** - * Help text for this command. - */ - helpText: string; + /** + * Execute the command with the specified arguments. + * + * @param args List of CLI arguments to pass to the command. + */ + execute(args: string[]): Promise; + /** + * Help text for this command. + */ + helpText: string; } /** @@ -24,11 +24,11 @@ export interface Command { * text to guide the user to correct their mistake. */ export class UsageError extends Error { - public readonly helpText: string; + public readonly helpText: string; - public constructor(message: string, helpText: string) { - super(message); + public constructor(message: string, helpText: string) { + super(message); - this.helpText = helpText; - } + this.helpText = helpText; + } } diff --git a/src/component.ts b/src/component.ts index c95d599..2bf59ea 100644 --- a/src/component.ts +++ b/src/component.ts @@ -7,46 +7,46 @@ * An in-memory representation of a renderable HTML element. */ export interface HTMLElement { - /** - * Name of the tag that gets output upon rendering. - */ - tag: string; - /** - * Record of attribute names and values that should be output in the opening - * tag. - */ - attributes: Record; - /** - * Child elements to render nested within this HTML element. - */ - children: Element[]; + /** + * Name of the tag that gets output upon rendering. + */ + tag: string; + /** + * Record of attribute names and values that should be output in the opening + * tag. + */ + attributes: Record; + /** + * Child elements to render nested within this HTML element. + */ + children: Element[]; } /** * All valid types of elements that can be rendered to HTML. */ export type Element = - | Element[] - | HTMLElement - | string - | number - | boolean - | undefined - | null; + | Element[] + | HTMLElement + | string + | number + | boolean + | undefined + | null; /** * Custom HTMLElement factory that can be parameterized by props. */ -export interface Component

{ - ( - props: P & { - children?: Element[]; - }, - ): HTMLElement; +export interface Component

> { + ( + props: P & { + children?: Element[]; + }, + ): HTMLElement; } -export const Fragment: Component<{}> = ({ children }) => ({ - tag: "#fragment", - attributes: {}, - children: children || [], +export const Fragment: Component = ({ children }) => ({ + tag: "#fragment", + attributes: {}, + children: children || [], }); diff --git a/src/config.ts b/src/config.ts index 2e91b13..f0cf805 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import * as path from "path"; +import * as path from "node:path"; import { decacheModule } from "./utils"; @@ -11,40 +11,40 @@ import { decacheModule } from "./utils"; * Paths used during configuration. */ export interface ConfigPaths { - rootDir: string; - outDir: string; - pagesDir: string; - staticAssetsDir: string; + rootDir: string; + outDir: string; + pagesDir: string; + staticAssetsDir: string; } /** * Hooks that allow user code to customize site rendering. */ export interface Hooks { - /** - * Hook that fires at the end of site rendering one all pages and assets are - * fully rendered. - */ - afterSiteRender(context: ConfigPaths): Promise | void; + /** + * Hook that fires at the end of site rendering one all pages and assets are + * fully rendered. + */ + afterSiteRender(context: ConfigPaths): Promise | void; } /** * User-provided configuration options. */ export type UserConfig = { - /** Hook implementations that allow customizing the rendering process. */ - hooks?: Partial; - /** Additional folders and files to watch by the development server. */ - watch?: string[]; + /** Hook implementations that allow customizing the rendering process. */ + hooks?: Partial; + /** Additional folders and files to watch by the development server. */ + watch?: string[]; }; /** * Fully-realized configuration for a websnacks site. */ export interface Config { - paths: ConfigPaths; - hooks: Hooks; - watch: string[]; + paths: ConfigPaths; + hooks: Hooks; + watch: string[]; } // eslint-disable-next-line @typescript-eslint/no-empty-function @@ -58,42 +58,44 @@ const noop = () => {}; * @return Fully-realized configuration. */ export const loadConfig = async (rootDir: string): Promise => { - let configPath; - let userConfig: UserConfig = {}; - // Attempt to load a websnacks.ts/js file in rootDir. - try { - configPath = require.resolve(path.resolve(rootDir, "websnacks")); - decacheModule(configPath); - // TODO: validate user config. - userConfig = await import(configPath); - } catch (error) { - // Use default config; - } - const outDir = path.join(rootDir, "public"); - const pagesDir = path.join(rootDir, "pages"); - const staticAssetsDir = path.join(rootDir, "static"); + let configPath = ""; + let userConfig: UserConfig = {}; + // Attempt to load a websnacks.ts/js file in rootDir. + try { + configPath = require.resolve(path.resolve(rootDir, "websnacks")); + decacheModule(configPath); + // TODO: validate user config. + userConfig = await import(configPath); + } catch (error) { + // Use default config; + } + const outDir = path.join(rootDir, "public"); + const pagesDir = path.join(rootDir, "pages"); + const staticAssetsDir = path.join(rootDir, "static"); - const watch = [pagesDir, staticAssetsDir]; - if (configPath != null) { - watch.push(path.relative(rootDir, configPath)); - } - if (userConfig.watch != null) { - for (const userWatch of userConfig.watch) { - watch.push(path.relative(rootDir, userWatch)); - } - } + const watch = [pagesDir, staticAssetsDir]; + if (configPath) { + watch.push(path.relative(rootDir, configPath)); + } + if (userConfig.watch != null) { + for (const userWatch of userConfig.watch) { + watch.push(path.relative(rootDir, userWatch)); + } + } - return { - paths: { - rootDir, - outDir, - pagesDir, - staticAssetsDir, - }, - hooks: { - afterSiteRender: noop, - ...userConfig.hooks, - }, - watch, - }; + return { + paths: { + rootDir, + outDir, + pagesDir, + staticAssetsDir, + }, + hooks: { + afterSiteRender: noop, + ...userConfig.hooks, + }, + watch, + }; }; + +export const defineConfig = (userConfig: UserConfig): UserConfig => userConfig; diff --git a/src/create-element.ts b/src/create-element.ts index d2d4398..e2f4bcf 100644 --- a/src/create-element.ts +++ b/src/create-element.ts @@ -3,8 +3,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { Component, Element, HTMLElement } from "./component"; -import { HTMLAttributes } from "./jsx"; +import type { Component, Element, HTMLElement } from "./component"; +import type { HTMLAttributes } from "./jsx"; import { flatDeep } from "./utils"; /** @@ -18,9 +18,9 @@ import { flatDeep } from "./utils"; * @return Fully-realized HTMLElement, ready for rendering. */ export function createElement

( - comp: Component

, - props: P, - ...children: Element[] + comp: Component

, + props: P, + ...children: Element[] ): HTMLElement; /** * Create an HTMLElement from a standard HTML5 tag. @@ -33,47 +33,44 @@ export function createElement

( * @return Fully-realized HTMLElement, ready for rendering. */ export function createElement( - tag: string, - attrs: HTMLAttributes | null, - ...children: Element[] + tag: string, + attrs: HTMLAttributes | null, + ...children: Element[] ): HTMLElement; export function createElement( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - type: string | Component, - props: object | null, - ...children: Element[] + type: string | Component, + props: object | null, + ...children: Element[] ): HTMLElement { - // Flatten the children array so we can accept arrays as children. - const normalizedChildren = flatDeep(children); - if (type instanceof Function) { - return type({ ...props, children: normalizedChildren }); - } + // Flatten the children array so we can accept arrays as children. + const normalizedChildren = flatDeep(children); + if (type instanceof Function) { + return type({ ...props, children: normalizedChildren }); + } - if (type !== type.toLowerCase()) { - console.warn(`constructed HTML5 tag with non-lowercase name ${type}`); - } - const attrs: Record = {}; - for (const [key, value] of Object.entries(props || {})) { - if (key === "dangerouslySetInnerHTML") { - if (children.length > 0) { - throw new Error( - 'An element with children may not have a "dangerouslySetInnerHTML" prop since children would be overriden', - ); - } - attrs[key] = value.__html; - continue; - } - if ( - typeof value !== "string" && - typeof value !== "number" && - typeof value !== "boolean" - ) { - console.warn( - `non-primitive attribute ${key} = ${JSON.stringify(value)}`, - ); - continue; - } - attrs[key] = value; - } - return { tag: type, attributes: attrs, children: normalizedChildren }; + if (type !== type.toLowerCase()) { + console.warn(`constructed HTML5 tag with non-lowercase name ${type}`); + } + const attrs: Record = {}; + for (const [key, value] of Object.entries(props || {})) { + if (key === "dangerouslySetInnerHTML") { + if (children.length > 0) { + throw new Error( + 'An element with children may not have a "dangerouslySetInnerHTML" prop since children would be overriden', + ); + } + attrs[key] = value.__html; + continue; + } + if ( + typeof value !== "string" && + typeof value !== "number" && + typeof value !== "boolean" + ) { + console.warn(`non-primitive attribute ${key} = ${JSON.stringify(value)}`); + continue; + } + attrs[key] = value; + } + return { tag: type, attributes: attrs, children: normalizedChildren }; } diff --git a/src/index.ts b/src/index.ts index bb1676f..ab79e4f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,6 @@ */ export { HTMLElement, Component, Fragment } from "./component"; -export { UserConfig as Config } from "./config"; +export { UserConfig as Config, defineConfig } from "./config"; export { createElement } from "./create-element"; export * from "./jsx"; diff --git a/src/jsx.ts b/src/jsx.ts index d450c4b..ce1c1ed 100644 --- a/src/jsx.ts +++ b/src/jsx.ts @@ -4,285 +4,285 @@ */ // eslint-disable-next-line @typescript-eslint/no-unused-vars -import { HTMLElement } from "./component"; +import type { HTMLElement } from "./component"; export interface RdfaAttributes { - about?: string; - datatype?: string; - inlist?: boolean; - prefix?: string; - property?: string; - resource?: string; - typeof?: string; - vocab?: string; + about?: string; + datatype?: string; + inlist?: boolean; + prefix?: string; + property?: string; + resource?: string; + typeof?: string; + vocab?: string; } export interface MicrodataAttributes { - itemProp?: string; - itemScope?: boolean; - itemType?: string; - itemID?: string; - itemRef?: string; + itemProp?: string; + itemScope?: boolean; + itemType?: string; + itemID?: string; + itemRef?: string; } export interface SetInnerHtmlAttributes { - dangerouslySetInnerHTML?: { __html: string }; + dangerouslySetInnerHTML?: { __html: string }; } export interface HTMLAttributes - extends RdfaAttributes, - MicrodataAttributes, - SetInnerHtmlAttributes { - accept?: string; - acceptCharset?: string; - accessKey?: string; - action?: string; - allowFullScreen?: boolean; - allowTransparency?: boolean; - alt?: string; - as?: string; - async?: boolean; - autoComplete?: string; - autoCorrect?: string; - autoFocus?: boolean; - autoPlay?: boolean; - capture?: boolean; - cellPadding?: number | string; - cellSpacing?: number | string; - charSet?: string; - challenge?: string; - checked?: boolean; - class?: string; - className?: string; - cols?: number; - colSpan?: number; - content?: string; - contentEditable?: boolean; - contextMenu?: string; - controls?: boolean; - controlsList?: string; - coords?: string; - crossOrigin?: string; - data?: string; - dateTime?: string; - default?: boolean; - defer?: boolean; - dir?: "auto" | "rtl" | "ltr"; - disabled?: boolean; - disableRemotePlayback?: boolean; - download?: boolean | string; - draggable?: boolean; - encType?: string; - form?: string; - formAction?: string; - formEncType?: string; - formMethod?: string; - formNoValidate?: boolean; - formTarget?: string; - frameBorder?: number | string; - headers?: string; - height?: number | string; - hidden?: boolean; - high?: number; - href?: string; - hrefLang?: string; - for?: string; - htmlFor?: string; - httpEquiv?: string; - icon?: string; - id?: string; - inputMode?: string; - integrity?: string; - is?: string; - keyParams?: string; - keyType?: string; - kind?: string; - label?: string; - lang?: string; - list?: string; - loop?: boolean; - low?: number; - manifest?: string; - marginHeight?: number; - marginWidth?: number; - max?: number | string; - maxLength?: number; - media?: string; - mediaGroup?: string; - method?: string; - min?: number | string; - minLength?: number; - multiple?: boolean; - muted?: boolean; - name?: string; - nonce?: string; - noValidate?: boolean; - open?: boolean; - optimum?: number; - pattern?: string; - placeholder?: string; - playsInline?: boolean; - poster?: string; - preload?: string; - radioGroup?: string; - readOnly?: boolean; - rel?: string; - required?: boolean; - role?: string; - rows?: number; - rowSpan?: number; - sandbox?: string; - scope?: string; - scoped?: boolean; - scrolling?: string; - seamless?: boolean; - selected?: boolean; - shape?: string; - size?: number; - sizes?: string; - slot?: string; - span?: number; - spellcheck?: boolean; - src?: string; - srcset?: string; - srcDoc?: string; - srcLang?: string; - srcSet?: string; - start?: number; - step?: number | string; - style?: string | { [key: string]: string | number }; - summary?: string; - tabIndex?: number; - target?: string; - title?: string; - type?: string; - useMap?: string; - value?: string | string[] | number; - volume?: string | number; - width?: number | string; - wmode?: string; - wrap?: string; + extends RdfaAttributes, + MicrodataAttributes, + SetInnerHtmlAttributes { + accept?: string; + acceptCharset?: string; + accessKey?: string; + action?: string; + allowFullScreen?: boolean; + allowTransparency?: boolean; + alt?: string; + as?: string; + async?: boolean; + autoComplete?: string; + autoCorrect?: string; + autoFocus?: boolean; + autoPlay?: boolean; + capture?: boolean; + cellPadding?: number | string; + cellSpacing?: number | string; + charSet?: string; + challenge?: string; + checked?: boolean; + class?: string; + className?: string; + cols?: number; + colSpan?: number; + content?: string; + contentEditable?: boolean; + contextMenu?: string; + controls?: boolean; + controlsList?: string; + coords?: string; + crossOrigin?: string; + data?: string; + dateTime?: string; + default?: boolean; + defer?: boolean; + dir?: "auto" | "rtl" | "ltr"; + disabled?: boolean; + disableRemotePlayback?: boolean; + download?: boolean | string; + draggable?: boolean; + encType?: string; + form?: string; + formAction?: string; + formEncType?: string; + formMethod?: string; + formNoValidate?: boolean; + formTarget?: string; + frameBorder?: number | string; + headers?: string; + height?: number | string; + hidden?: boolean; + high?: number; + href?: string; + hrefLang?: string; + for?: string; + htmlFor?: string; + httpEquiv?: string; + icon?: string; + id?: string; + inputMode?: string; + integrity?: string; + is?: string; + keyParams?: string; + keyType?: string; + kind?: string; + label?: string; + lang?: string; + list?: string; + loop?: boolean; + low?: number; + manifest?: string; + marginHeight?: number; + marginWidth?: number; + max?: number | string; + maxLength?: number; + media?: string; + mediaGroup?: string; + method?: string; + min?: number | string; + minLength?: number; + multiple?: boolean; + muted?: boolean; + name?: string; + nonce?: string; + noValidate?: boolean; + open?: boolean; + optimum?: number; + pattern?: string; + placeholder?: string; + playsInline?: boolean; + poster?: string; + preload?: string; + radioGroup?: string; + readOnly?: boolean; + rel?: string; + required?: boolean; + role?: string; + rows?: number; + rowSpan?: number; + sandbox?: string; + scope?: string; + scoped?: boolean; + scrolling?: string; + seamless?: boolean; + selected?: boolean; + shape?: string; + size?: number; + sizes?: string; + slot?: string; + span?: number; + spellcheck?: boolean; + src?: string; + srcset?: string; + srcDoc?: string; + srcLang?: string; + srcSet?: string; + start?: number; + step?: number | string; + style?: string | { [key: string]: string | number }; + summary?: string; + tabIndex?: number; + target?: string; + title?: string; + type?: string; + useMap?: string; + value?: string | string[] | number; + volume?: string | number; + width?: number | string; + wmode?: string; + wrap?: string; } declare global { - namespace JSX { - type Element = HTMLElement; - type IntrinsicElements = { - a: HTMLAttributes; - abbr: HTMLAttributes; - address: HTMLAttributes; - area: HTMLAttributes; - article: HTMLAttributes; - aside: HTMLAttributes; - audio: HTMLAttributes; - b: HTMLAttributes; - base: HTMLAttributes; - bdi: HTMLAttributes; - bdo: HTMLAttributes; - big: HTMLAttributes; - blockquote: HTMLAttributes; - body: HTMLAttributes; - br: HTMLAttributes; - button: HTMLAttributes; - canvas: HTMLAttributes; - caption: HTMLAttributes; - cite: HTMLAttributes; - code: HTMLAttributes; - col: HTMLAttributes; - colgroup: HTMLAttributes; - data: HTMLAttributes; - datalist: HTMLAttributes; - dd: HTMLAttributes; - del: HTMLAttributes; - details: HTMLAttributes; - dfn: HTMLAttributes; - dialog: HTMLAttributes; - div: HTMLAttributes; - dl: HTMLAttributes; - dt: HTMLAttributes; - em: HTMLAttributes; - embed: HTMLAttributes; - fieldset: HTMLAttributes; - figcaption: HTMLAttributes; - figure: HTMLAttributes; - footer: HTMLAttributes; - form: HTMLAttributes; - h1: HTMLAttributes; - h2: HTMLAttributes; - h3: HTMLAttributes; - h4: HTMLAttributes; - h5: HTMLAttributes; - h6: HTMLAttributes; - head: HTMLAttributes; - header: HTMLAttributes; - hgroup: HTMLAttributes; - hr: HTMLAttributes; - html: HTMLAttributes; - i: HTMLAttributes; - iframe: HTMLAttributes; - img: HTMLAttributes; - input: HTMLAttributes; - ins: HTMLAttributes; - kbd: HTMLAttributes; - keygen: HTMLAttributes; - label: HTMLAttributes; - legend: HTMLAttributes; - li: HTMLAttributes; - link: HTMLAttributes; - main: HTMLAttributes; - map: HTMLAttributes; - mark: HTMLAttributes; - marquee: HTMLAttributes; - menu: HTMLAttributes; - menuitem: HTMLAttributes; - meta: HTMLAttributes; - meter: HTMLAttributes; - nav: HTMLAttributes; - noscript: HTMLAttributes; - object: HTMLAttributes; - ol: HTMLAttributes; - optgroup: HTMLAttributes; - option: HTMLAttributes; - output: HTMLAttributes; - p: HTMLAttributes; - param: HTMLAttributes; - picture: HTMLAttributes; - pre: HTMLAttributes; - progress: HTMLAttributes; - q: HTMLAttributes; - rp: HTMLAttributes; - rt: HTMLAttributes; - ruby: HTMLAttributes; - s: HTMLAttributes; - samp: HTMLAttributes; - script: HTMLAttributes; - section: HTMLAttributes; - select: HTMLAttributes; - slot: HTMLAttributes; - small: HTMLAttributes; - source: HTMLAttributes; - span: HTMLAttributes; - strong: HTMLAttributes; - style: HTMLAttributes; - sub: HTMLAttributes; - summary: HTMLAttributes; - sup: HTMLAttributes; - table: HTMLAttributes; - tbody: HTMLAttributes; - td: HTMLAttributes; - textarea: HTMLAttributes; - tfoot: HTMLAttributes; - th: HTMLAttributes; - thead: HTMLAttributes; - time: HTMLAttributes; - title: HTMLAttributes; - tr: HTMLAttributes; - track: HTMLAttributes; - u: HTMLAttributes; - ul: HTMLAttributes; - var: HTMLAttributes; - video: HTMLAttributes; - wbr: HTMLAttributes; - }; - } + namespace JSX { + type Element = HTMLElement; + type IntrinsicElements = { + a: HTMLAttributes; + abbr: HTMLAttributes; + address: HTMLAttributes; + area: HTMLAttributes; + article: HTMLAttributes; + aside: HTMLAttributes; + audio: HTMLAttributes; + b: HTMLAttributes; + base: HTMLAttributes; + bdi: HTMLAttributes; + bdo: HTMLAttributes; + big: HTMLAttributes; + blockquote: HTMLAttributes; + body: HTMLAttributes; + br: HTMLAttributes; + button: HTMLAttributes; + canvas: HTMLAttributes; + caption: HTMLAttributes; + cite: HTMLAttributes; + code: HTMLAttributes; + col: HTMLAttributes; + colgroup: HTMLAttributes; + data: HTMLAttributes; + datalist: HTMLAttributes; + dd: HTMLAttributes; + del: HTMLAttributes; + details: HTMLAttributes; + dfn: HTMLAttributes; + dialog: HTMLAttributes; + div: HTMLAttributes; + dl: HTMLAttributes; + dt: HTMLAttributes; + em: HTMLAttributes; + embed: HTMLAttributes; + fieldset: HTMLAttributes; + figcaption: HTMLAttributes; + figure: HTMLAttributes; + footer: HTMLAttributes; + form: HTMLAttributes; + h1: HTMLAttributes; + h2: HTMLAttributes; + h3: HTMLAttributes; + h4: HTMLAttributes; + h5: HTMLAttributes; + h6: HTMLAttributes; + head: HTMLAttributes; + header: HTMLAttributes; + hgroup: HTMLAttributes; + hr: HTMLAttributes; + html: HTMLAttributes; + i: HTMLAttributes; + iframe: HTMLAttributes; + img: HTMLAttributes; + input: HTMLAttributes; + ins: HTMLAttributes; + kbd: HTMLAttributes; + keygen: HTMLAttributes; + label: HTMLAttributes; + legend: HTMLAttributes; + li: HTMLAttributes; + link: HTMLAttributes; + main: HTMLAttributes; + map: HTMLAttributes; + mark: HTMLAttributes; + marquee: HTMLAttributes; + menu: HTMLAttributes; + menuitem: HTMLAttributes; + meta: HTMLAttributes; + meter: HTMLAttributes; + nav: HTMLAttributes; + noscript: HTMLAttributes; + object: HTMLAttributes; + ol: HTMLAttributes; + optgroup: HTMLAttributes; + option: HTMLAttributes; + output: HTMLAttributes; + p: HTMLAttributes; + param: HTMLAttributes; + picture: HTMLAttributes; + pre: HTMLAttributes; + progress: HTMLAttributes; + q: HTMLAttributes; + rp: HTMLAttributes; + rt: HTMLAttributes; + ruby: HTMLAttributes; + s: HTMLAttributes; + samp: HTMLAttributes; + script: HTMLAttributes; + section: HTMLAttributes; + select: HTMLAttributes; + slot: HTMLAttributes; + small: HTMLAttributes; + source: HTMLAttributes; + span: HTMLAttributes; + strong: HTMLAttributes; + style: HTMLAttributes; + sub: HTMLAttributes; + summary: HTMLAttributes; + sup: HTMLAttributes; + table: HTMLAttributes; + tbody: HTMLAttributes; + td: HTMLAttributes; + textarea: HTMLAttributes; + tfoot: HTMLAttributes; + th: HTMLAttributes; + thead: HTMLAttributes; + time: HTMLAttributes; + title: HTMLAttributes; + tr: HTMLAttributes; + track: HTMLAttributes; + u: HTMLAttributes; + ul: HTMLAttributes; + var: HTMLAttributes; + video: HTMLAttributes; + wbr: HTMLAttributes; + }; + } } diff --git a/src/render.ts b/src/render.ts index 60cdb73..85fda2e 100644 --- a/src/render.ts +++ b/src/render.ts @@ -3,89 +3,87 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { Element, HTMLElement } from "./component"; +import type { Element, HTMLElement } from "./component"; const HTML_ESCAPES: { [char: string]: string } = { - "&": "&", - "<": "<", - ">": ">", + "&": "&", + "<": "<", + ">": ">", }; const escapeHtml = (text: string): string => - text.replace(/[&<>]/g, (t) => HTML_ESCAPES[t]); + text.replace(/[&<>]/g, (t) => HTML_ESCAPES[t]); const escapeAttr = (text: string): string => text.replace(/"/g, """); const renderElement = (elem: Element): string => { - // Ignore null and true/false to support nicer JSX conditional syntax with - // &&, ||, !! operators. - if (elem == null || typeof elem === "boolean") { - return ""; - } - if (typeof elem === "number") { - return elem.toString(); - } - if (typeof elem === "string") { - return escapeHtml(elem); - } - if (Array.isArray(elem)) { - return elem.map((e) => renderElement(e)).join(""); - } + // Ignore null and true/false to support nicer JSX conditional syntax with + // &&, ||, !! operators. + if (elem == null || typeof elem === "boolean") { + return ""; + } + if (typeof elem === "number") { + return elem.toString(); + } + if (typeof elem === "string") { + return escapeHtml(elem); + } + if (Array.isArray(elem)) { + return elem.map((e) => renderElement(e)).join(""); + } - let output = ""; - output += startTag(elem); - if (elem.attributes.dangerouslySetInnerHTML != null) { - output += elem.attributes.dangerouslySetInnerHTML; - } else { - for (const child of elem.children) { - output += renderElement(child); - } - } - output += endTag(elem); - return output; + let output = ""; + output += startTag(elem); + if (elem.attributes.dangerouslySetInnerHTML != null) { + output += elem.attributes.dangerouslySetInnerHTML; + } else { + for (const child of elem.children) { + output += renderElement(child); + } + } + output += endTag(elem); + return output; }; const startTag = (elem: HTMLElement): string => { - if (elem.tag === "#fragment") { - return ""; - } + if (elem.tag === "#fragment") { + return ""; + } - let output = `<${escapeHtml(elem.tag)}`; + let output = `<${escapeHtml(elem.tag)}`; - for (const [attrName, attrValue] of Object.entries(elem.attributes)) { - // Handle boolean attributes with a false value by not outputting the - // attribute at all. - if (attrValue === false) { - continue; - } + for (const [attrName, attrValue] of Object.entries(elem.attributes)) { + // Handle boolean attributes with a false value by not outputting the + // attribute at all. + if (attrValue === false) { + continue; + } - // Ignore the special attr for setting raw inner HTML. - if (attrName === "dangerouslySetInnerHTML") { - continue; - } + // Ignore the special attr for setting raw inner HTML. + if (attrName === "dangerouslySetInnerHTML") { + continue; + } - let normalizedAttrName = escapeHtml(attrName.toLowerCase()); - if (normalizedAttrName === "classname") { - normalizedAttrName = "class"; - } - if (attrValue === true) { - output += ` ${normalizedAttrName}=""`; - } else { - output += ` ${normalizedAttrName}="${escapeAttr( - attrValue.toString(), - )}"`; - } - } + let normalizedAttrName = escapeHtml(attrName.toLowerCase()); + if (normalizedAttrName === "classname") { + normalizedAttrName = "class"; + } + if (attrValue === true) { + output += ` ${normalizedAttrName}=""`; + } else { + output += ` ${normalizedAttrName}="${escapeAttr(attrValue.toString())}"`; + } + } - output += ">"; - return output; + output += ">"; + return output; }; const endTag = (elem: HTMLElement): string => { - if (elem.tag === "#fragment") { - return ""; - } - return ``; + if (elem.tag === "#fragment") { + return ""; + } + return ``; }; /** @@ -97,23 +95,23 @@ const endTag = (elem: HTMLElement): string => { * @return Fully rendered HTML document as a string. */ export const renderPage = (rootElem: Element): string => { - if (rootElem == undefined) { - throw new Error(`root page element cannot be null`); - } - if (typeof rootElem !== "object" || !("tag" in rootElem)) { - throw new Error( - `root page element must be a valid HTMLElement, got ${JSON.stringify( - rootElem, - )}`, - ); - } - if (rootElem.tag.toLowerCase() !== "html") { - throw new Error( - `attempted to render page with non-HTML root element ${rootElem.tag}`, - ); - } + if (rootElem == null) { + throw new Error("root page element cannot be null"); + } + if (typeof rootElem !== "object" || !("tag" in rootElem)) { + throw new Error( + `root page element must be a valid HTMLElement, got ${JSON.stringify( + rootElem, + )}`, + ); + } + if (rootElem.tag.toLowerCase() !== "html") { + throw new Error( + `attempted to render page with non-HTML root element ${rootElem.tag}`, + ); + } - let output = ""; - output += renderElement(rootElem); - return output; + let output = ""; + output += renderElement(rootElem); + return output; }; diff --git a/src/utils/decache-module.ts b/src/utils/decache-module.ts index 3bfd4e6..e0c6ac9 100644 --- a/src/utils/decache-module.ts +++ b/src/utils/decache-module.ts @@ -6,35 +6,35 @@ import { isErrnoException } from "./error"; const resolveModulePath = (importPath: string): string | undefined => { - try { - return require.resolve(importPath); - } catch (error) { - if ( - error instanceof Error && - isErrnoException(error) && - error.code === "MODULE_NOT_FOUND" - ) { - return; - } - throw error; - } + try { + return require.resolve(importPath); + } catch (error) { + if ( + error instanceof Error && + isErrnoException(error) && + error.code === "MODULE_NOT_FOUND" + ) { + return; + } + throw error; + } }; const removeParentModuleRef = (mod: NodeModule): void => { - const parent = mod.parent; - if (parent == null) { - return; - } + const parent = mod.parent; + if (parent == null) { + return; + } - const siblings = parent.children; - const nSiblings = siblings.length; - for (let i = nSiblings - 1; i >= 0; i--) { - const sibling = siblings[i]; - if (sibling.id === mod.id) { - siblings.splice(i, 1); - return; - } - } + const siblings = parent.children; + const nSiblings = siblings.length; + for (let i = nSiblings - 1; i >= 0; i--) { + const sibling = siblings[i]; + if (sibling.id === mod.id) { + siblings.splice(i, 1); + return; + } + } }; /** @@ -47,29 +47,29 @@ const removeParentModuleRef = (mod: NodeModule): void => { * @throws Error if the module could not be resolved due to filesystem error. */ export const decacheModule = (importPath: string): void => { - const modulePath = resolveModulePath(importPath); - if (modulePath == null) { - return; - } + const modulePath = resolveModulePath(importPath); + if (modulePath == null) { + return; + } - // DFS the module dependency tree, using iteration to avoid stack size - // exceeded exceptions. - const modsToCheck: NodeModule[] = []; - const visited: Set = new Set(); - let currentMod: NodeModule | undefined = require.cache[modulePath]; - while (currentMod != null) { - if (visited.has(currentMod.id)) { - currentMod = modsToCheck.pop(); - continue; - } + // DFS the module dependency tree, using iteration to avoid stack size + // exceeded exceptions. + const modsToCheck: NodeModule[] = []; + const visited: Set = new Set(); + let currentMod: NodeModule | undefined = require.cache[modulePath]; + while (currentMod != null) { + if (visited.has(currentMod.id)) { + currentMod = modsToCheck.pop(); + continue; + } - removeParentModuleRef(currentMod); - delete require.cache[currentMod.id]; - for (const childMod of currentMod.children) { - modsToCheck.push(childMod); - } + removeParentModuleRef(currentMod); + delete require.cache[currentMod.id]; + for (const childMod of currentMod.children) { + modsToCheck.push(childMod); + } - visited.add(currentMod.id); - currentMod = modsToCheck.pop(); - } + visited.add(currentMod.id); + currentMod = modsToCheck.pop(); + } }; diff --git a/src/utils/error.ts b/src/utils/error.ts index 9490368..76b351b 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -1,3 +1,3 @@ export const isErrnoException = ( - error: Error, + error: Error, ): error is NodeJS.ErrnoException => "code" in error; diff --git a/src/utils/index.ts b/src/utils/index.ts index 2cce921..a47ffb3 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,8 +3,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { promises as fs } from "fs"; -import * as path from "path"; +import { promises as fs } from "node:fs"; +import * as path from "node:path"; export { decacheModule } from "./decache-module"; @@ -16,17 +16,17 @@ export { decacheModule } from "./decache-module"; * @return Generator that yields the files found while walking the directory. */ export const walkDir = async function* ( - dirPath: string, + dirPath: string, ): AsyncGenerator { - const dirEnts = await fs.readdir(dirPath, { withFileTypes: true }); - for (const dirEnt of dirEnts) { - if (dirEnt.isDirectory()) { - yield* walkDir(path.join(dirPath, dirEnt.name)); - } - if (dirEnt.isFile()) { - yield path.join(dirPath, dirEnt.name); - } - } + const dirEnts = await fs.readdir(dirPath, { withFileTypes: true }); + for (const dirEnt of dirEnts) { + if (dirEnt.isDirectory()) { + yield* walkDir(path.join(dirPath, dirEnt.name)); + } + if (dirEnt.isFile()) { + yield path.join(dirPath, dirEnt.name); + } + } }; export type Flattenable = Array>; @@ -39,13 +39,13 @@ export type Flattenable = Array>; * @return Flattened array. */ export const flatDeep = (arr: Flattenable): T[] => { - const flattenedArr: T[] = []; - for (const val of arr) { - if (Array.isArray(val)) { - flattenedArr.push(...flatDeep(val)); - } else { - flattenedArr.push(val); - } - } - return flattenedArr; + const flattenedArr: T[] = []; + for (const val of arr) { + if (Array.isArray(val)) { + flattenedArr.push(...flatDeep(val)); + } else { + flattenedArr.push(val); + } + } + return flattenedArr; }; diff --git a/test/e2e/build.tsx b/test/e2e/build.tsx index 9daba49..ca4c6cd 100644 --- a/test/e2e/build.tsx +++ b/test/e2e/build.tsx @@ -3,149 +3,149 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { promises as fs } from "fs"; -import * as path from "path"; +import { promises as fs } from "node:fs"; +import * as path from "node:path"; import { - npmCmd, - runCommand, - WEBSNACKS_BIN_PATH, - WEBSNACKS_REPO_ROOT, - withTempDir, + WEBSNACKS_BIN_PATH, + WEBSNACKS_REPO_ROOT, + npmCmd, + runCommand, + withTempDir, } from "../helpers/e2e"; import { testSuite } from "../lib"; testSuite("build command", ({ test }) => { - test("runs without throwing error", async () => { - await withTempDir(async (tempDirPath) => { - await fs.writeFile( - path.join(tempDirPath, "tsconfig.json"), - JSON.stringify({ - compilerOptions: { - esModuleInterop: true, - module: "CommonJS", - moduleResolution: "node", - jsx: "react", - jsxFactory: "createElement", - target: "ES2018", - lib: ["ES2018"], - strict: true, - noUnusedLocals: true, - noUnusedParameters: true, - noImplicitReturns: true, - noFallthroughCasesInSwitch: true, - }, - include: ["components/**/*", "pages/**/*"], - }), - { - encoding: "utf8", - }, - ); - await fs.writeFile( - path.join(tempDirPath, "websnacks.ts"), - ` + test("runs without throwing error", async () => { + await withTempDir(async (tempDirPath) => { + await fs.writeFile( + path.join(tempDirPath, "tsconfig.json"), + JSON.stringify({ + compilerOptions: { + esModuleInterop: true, + module: "CommonJS", + moduleResolution: "node", + jsx: "react", + jsxFactory: "createElement", + target: "ES2018", + lib: ["ES2018"], + strict: true, + noUnusedLocals: true, + noUnusedParameters: true, + noImplicitReturns: true, + noFallthroughCasesInSwitch: true, + }, + include: ["components/**/*", "pages/**/*"], + }), + { + encoding: "utf8", + }, + ); + await fs.writeFile( + path.join(tempDirPath, "websnacks.ts"), + ` import { Config } from "websnacks"; const config: Config = { watch: [], }; export = config; `, - { - encoding: "utf8", - }, - ); - const pagesPath = path.join(tempDirPath, "pages"); - await fs.mkdir(pagesPath); - await fs.writeFile( - path.join(pagesPath, "index.tsx"), - ` + { + encoding: "utf8", + }, + ); + const pagesPath = path.join(tempDirPath, "pages"); + await fs.mkdir(pagesPath); + await fs.writeFile( + path.join(pagesPath, "index.tsx"), + ` import { createElement } from "websnacks"; export const page = () => ; `, - { - encoding: "utf8", - }, - ); - await fs.writeFile( - path.join(tempDirPath, "package.json"), - JSON.stringify({ - devDependencies: { - websnacks: `file:${WEBSNACKS_REPO_ROOT}`, - }, - }), - { encoding: "utf8" }, - ); - await runCommand(npmCmd, ["install", "--silent"], { - cwd: tempDirPath, - }).complete; - const cmd = runCommand( - "node", - [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "build"], - { - cwd: tempDirPath, - }, - ); - await cmd.complete; - }); - }); + { + encoding: "utf8", + }, + ); + await fs.writeFile( + path.join(tempDirPath, "package.json"), + JSON.stringify({ + devDependencies: { + websnacks: `file:${WEBSNACKS_REPO_ROOT}`, + }, + }), + { encoding: "utf8" }, + ); + await runCommand(npmCmd, ["install", "--silent"], { + cwd: tempDirPath, + }).complete; + const cmd = runCommand( + "node", + [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "build"], + { + cwd: tempDirPath, + }, + ); + await cmd.complete; + }); + }); - test("works without config file", async () => { - await withTempDir(async (tempDirPath) => { - await fs.writeFile( - path.join(tempDirPath, "tsconfig.json"), - JSON.stringify({ - compilerOptions: { - esModuleInterop: true, - module: "CommonJS", - moduleResolution: "node", - jsx: "react", - jsxFactory: "createElement", - target: "ES2018", - lib: ["ES2018"], - strict: true, - noUnusedLocals: true, - noUnusedParameters: true, - noImplicitReturns: true, - noFallthroughCasesInSwitch: true, - }, - include: ["components/**/*", "pages/**/*"], - }), - { - encoding: "utf8", - }, - ); - const pagesPath = path.join(tempDirPath, "pages"); - await fs.mkdir(pagesPath); - await fs.writeFile( - path.join(pagesPath, "index.tsx"), - ` + test("works without config file", async () => { + await withTempDir(async (tempDirPath) => { + await fs.writeFile( + path.join(tempDirPath, "tsconfig.json"), + JSON.stringify({ + compilerOptions: { + esModuleInterop: true, + module: "CommonJS", + moduleResolution: "node", + jsx: "react", + jsxFactory: "createElement", + target: "ES2018", + lib: ["ES2018"], + strict: true, + noUnusedLocals: true, + noUnusedParameters: true, + noImplicitReturns: true, + noFallthroughCasesInSwitch: true, + }, + include: ["components/**/*", "pages/**/*"], + }), + { + encoding: "utf8", + }, + ); + const pagesPath = path.join(tempDirPath, "pages"); + await fs.mkdir(pagesPath); + await fs.writeFile( + path.join(pagesPath, "index.tsx"), + ` import { createElement } from "websnacks"; export const page = () => ; `, - { - encoding: "utf8", - }, - ); - await fs.writeFile( - path.join(tempDirPath, "package.json"), - JSON.stringify({ - devDependencies: { - websnacks: `file:${WEBSNACKS_REPO_ROOT}`, - }, - }), - { encoding: "utf8" }, - ); - await runCommand(npmCmd, ["install", "--silent"], { - cwd: tempDirPath, - }).complete; - const cmd = runCommand( - "node", - [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "build"], - { - cwd: tempDirPath, - }, - ); - await cmd.complete; - }); - }); + { + encoding: "utf8", + }, + ); + await fs.writeFile( + path.join(tempDirPath, "package.json"), + JSON.stringify({ + devDependencies: { + websnacks: `file:${WEBSNACKS_REPO_ROOT}`, + }, + }), + { encoding: "utf8" }, + ); + await runCommand(npmCmd, ["install", "--silent"], { + cwd: tempDirPath, + }).complete; + const cmd = runCommand( + "node", + [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "build"], + { + cwd: tempDirPath, + }, + ); + await cmd.complete; + }); + }); }); diff --git a/test/e2e/dev.tsx b/test/e2e/dev.tsx index a32c183..78f9e1c 100644 --- a/test/e2e/dev.tsx +++ b/test/e2e/dev.tsx @@ -3,158 +3,158 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { promises as fs } from "fs"; -import * as path from "path"; +import { promises as fs } from "node:fs"; +import * as path from "node:path"; import { - npmCmd, - runCommand, - wait, - WEBSNACKS_BIN_PATH, - WEBSNACKS_REPO_ROOT, - withTempDir, + WEBSNACKS_BIN_PATH, + WEBSNACKS_REPO_ROOT, + npmCmd, + runCommand, + wait, + withTempDir, } from "../helpers/e2e"; import { testSuite } from "../lib"; testSuite("dev command", ({ test, expect }) => { - test("starts without throwing error", async () => { - await withTempDir(async (tempDirPath) => { - await fs.writeFile( - path.join(tempDirPath, "tsconfig.json"), - JSON.stringify({ - compilerOptions: { - esModuleInterop: true, - module: "CommonJS", - moduleResolution: "node", - jsx: "react", - jsxFactory: "createElement", - target: "ES2018", - lib: ["ES2018"], - strict: true, - noUnusedLocals: true, - noUnusedParameters: true, - noImplicitReturns: true, - noFallthroughCasesInSwitch: true, - }, - include: ["components/**/*", "pages/**/*"], - }), - { - encoding: "utf8", - }, - ); - await fs.writeFile( - path.join(tempDirPath, "websnacks.ts"), - ` + test("starts without throwing error", async () => { + await withTempDir(async (tempDirPath) => { + await fs.writeFile( + path.join(tempDirPath, "tsconfig.json"), + JSON.stringify({ + compilerOptions: { + esModuleInterop: true, + module: "CommonJS", + moduleResolution: "node", + jsx: "react", + jsxFactory: "createElement", + target: "ES2018", + lib: ["ES2018"], + strict: true, + noUnusedLocals: true, + noUnusedParameters: true, + noImplicitReturns: true, + noFallthroughCasesInSwitch: true, + }, + include: ["components/**/*", "pages/**/*"], + }), + { + encoding: "utf8", + }, + ); + await fs.writeFile( + path.join(tempDirPath, "websnacks.ts"), + ` import { Config } from "websnacks"; const config: Config = { watch: [], }; export = config; `, - { - encoding: "utf8", - }, - ); - const pagesPath = path.join(tempDirPath, "pages"); - await fs.mkdir(pagesPath); - await fs.writeFile( - path.join(pagesPath, "index.tsx"), - ` + { + encoding: "utf8", + }, + ); + const pagesPath = path.join(tempDirPath, "pages"); + await fs.mkdir(pagesPath); + await fs.writeFile( + path.join(pagesPath, "index.tsx"), + ` import { createElement } from "websnacks"; export const page = () => ; `, - { - encoding: "utf8", - }, - ); - await fs.writeFile( - path.join(tempDirPath, "package.json"), - JSON.stringify({ - devDependencies: { - websnacks: `file:${WEBSNACKS_REPO_ROOT}`, - }, - }), - { encoding: "utf8" }, - ); - await runCommand(npmCmd, ["install", "--silent"], { - cwd: tempDirPath, - }).complete; - const cmd = runCommand( - "node", - [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "dev"], - { - cwd: tempDirPath, - }, - ); - // FIXME: This test is a bit brittle due to relying on timeouts. - await wait(10_000); - cmd.process.kill(); - const stdout = await cmd.complete; - expect(stdout).toStartWith("Listening at"); - }); - }); + { + encoding: "utf8", + }, + ); + await fs.writeFile( + path.join(tempDirPath, "package.json"), + JSON.stringify({ + devDependencies: { + websnacks: `file:${WEBSNACKS_REPO_ROOT}`, + }, + }), + { encoding: "utf8" }, + ); + await runCommand(npmCmd, ["install", "--silent"], { + cwd: tempDirPath, + }).complete; + const cmd = runCommand( + "node", + [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "dev"], + { + cwd: tempDirPath, + }, + ); + // FIXME: This test is a bit brittle due to relying on timeouts. + await wait(10_000); + cmd.process.kill(); + const stdout = await cmd.complete; + expect(stdout).toStartWith("Listening at"); + }); + }); - test("works without config file", async () => { - await withTempDir(async (tempDirPath) => { - await fs.writeFile( - path.join(tempDirPath, "tsconfig.json"), - JSON.stringify({ - compilerOptions: { - esModuleInterop: true, - module: "CommonJS", - moduleResolution: "node", - jsx: "react", - jsxFactory: "createElement", - target: "ES2018", - lib: ["ES2018"], - strict: true, - noUnusedLocals: true, - noUnusedParameters: true, - noImplicitReturns: true, - noFallthroughCasesInSwitch: true, - }, - include: ["components/**/*", "pages/**/*"], - }), - { - encoding: "utf8", - }, - ); - const pagesPath = path.join(tempDirPath, "pages"); - await fs.mkdir(pagesPath); - await fs.writeFile( - path.join(pagesPath, "index.tsx"), - ` + test("works without config file", async () => { + await withTempDir(async (tempDirPath) => { + await fs.writeFile( + path.join(tempDirPath, "tsconfig.json"), + JSON.stringify({ + compilerOptions: { + esModuleInterop: true, + module: "CommonJS", + moduleResolution: "node", + jsx: "react", + jsxFactory: "createElement", + target: "ES2018", + lib: ["ES2018"], + strict: true, + noUnusedLocals: true, + noUnusedParameters: true, + noImplicitReturns: true, + noFallthroughCasesInSwitch: true, + }, + include: ["components/**/*", "pages/**/*"], + }), + { + encoding: "utf8", + }, + ); + const pagesPath = path.join(tempDirPath, "pages"); + await fs.mkdir(pagesPath); + await fs.writeFile( + path.join(pagesPath, "index.tsx"), + ` import { createElement } from "websnacks"; export const page = () => ; `, - { - encoding: "utf8", - }, - ); - await fs.writeFile( - path.join(tempDirPath, "package.json"), - JSON.stringify({ - devDependencies: { - websnacks: `file:${WEBSNACKS_REPO_ROOT}`, - }, - }), - { encoding: "utf8" }, - ); - await runCommand(npmCmd, ["install", "--silent"], { - cwd: tempDirPath, - }).complete; - const cmd = runCommand( - "node", - [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "dev"], - { - cwd: tempDirPath, - }, - ); - // FIXME: This test is a bit brittle due to relying on timeouts. - await wait(10_000); - cmd.process.kill(); - const stdout = await cmd.complete; - expect(stdout).toStartWith("Listening at"); - }); - }); + { + encoding: "utf8", + }, + ); + await fs.writeFile( + path.join(tempDirPath, "package.json"), + JSON.stringify({ + devDependencies: { + websnacks: `file:${WEBSNACKS_REPO_ROOT}`, + }, + }), + { encoding: "utf8" }, + ); + await runCommand(npmCmd, ["install", "--silent"], { + cwd: tempDirPath, + }).complete; + const cmd = runCommand( + "node", + [WEBSNACKS_BIN_PATH, "-r", "ts-node/register", "dev"], + { + cwd: tempDirPath, + }, + ); + // FIXME: This test is a bit brittle due to relying on timeouts. + await wait(10_000); + cmd.process.kill(); + const stdout = await cmd.complete; + expect(stdout).toStartWith("Listening at"); + }); + }); }); diff --git a/test/helpers/e2e.ts b/test/helpers/e2e.ts index de31b74..c1e2097 100644 --- a/test/helpers/e2e.ts +++ b/test/helpers/e2e.ts @@ -3,10 +3,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { ChildProcess, spawn } from "child_process"; -import { promises as fs } from "fs"; -import * as os from "os"; -import * as path from "path"; +import { type ChildProcess, spawn } from "node:child_process"; +import { promises as fs } from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; /** * Set a timeout and wait for at least the specified number of milliseconds, @@ -15,9 +15,9 @@ import * as path from "path"; * @param timeMs Time in milliseconds to wait. */ export const wait = async (timeMs: number): Promise => { - return new Promise((resolve) => { - setTimeout(() => resolve(), timeMs); - }); + return new Promise((resolve) => { + setTimeout(() => resolve(), timeMs); + }); }; const TEMP_PATH = path.resolve(__dirname, "..", "..", ".temp"); @@ -36,15 +36,15 @@ const TEMP_PATH = path.resolve(__dirname, "..", "..", ".temp"); * directory path as its only argument. */ export const withTempDir = async ( - op: (tempDirPath: string) => Promise | void, + op: (tempDirPath: string) => Promise | void, ): Promise => { - await fs.mkdir(TEMP_PATH, { recursive: true }); - const tempDirPath = await fs.mkdtemp(`${TEMP_PATH}/`); - try { - await op(tempDirPath); - } catch (error) { - throw new Error(`(${tempDirPath}): ${error}`); - } + await fs.mkdir(TEMP_PATH, { recursive: true }); + const tempDirPath = await fs.mkdtemp(`${TEMP_PATH}/`); + try { + await op(tempDirPath); + } catch (error) { + throw new Error(`(${tempDirPath}): ${error}`); + } }; /** @@ -55,47 +55,47 @@ export const WEBSNACKS_REPO_ROOT = path.resolve(__dirname, "..", ".."); * Fully resolved path to the websnacks CLI script in this repository. */ export const WEBSNACKS_BIN_PATH = path.join( - WEBSNACKS_REPO_ROOT, - "bin", - "websnacks.js", + WEBSNACKS_REPO_ROOT, + "bin", + "websnacks.js", ); /** * A handle to an asynchronous shell command run in a subprocess. */ export interface AsyncCommand { - /** - * Promise that resolves with the stdout of the subprocess once the - * subprocess exits with a zero-code. - * - * The promise rejects if the subprocess exits with a non-zero code, the - * subprocess writes to its stderr, or the command failed to spawn. - */ - complete: Promise; - /** - * Handle to to child process for event-based process manipulation. - */ - process: ChildProcess; + /** + * Promise that resolves with the stdout of the subprocess once the + * subprocess exits with a zero-code. + * + * The promise rejects if the subprocess exits with a non-zero code, the + * subprocess writes to its stderr, or the command failed to spawn. + */ + complete: Promise; + /** + * Handle to to child process for event-based process manipulation. + */ + process: ChildProcess; } /** * Options used to configure {@link runCommand}. */ export interface CliOptions { - /** - * Working directory where the command should be run. Defaults to the - * current working directory. - */ - cwd?: string; - /** - * Timeout in milliseconds after which a command that hasn't exited will - * reject the promise and kill the subprocess. - */ - timeoutMs?: number; + /** + * Working directory where the command should be run. Defaults to the + * current working directory. + */ + cwd?: string; + /** + * Timeout in milliseconds after which a command that hasn't exited will + * reject the promise and kill the subprocess. + */ + timeoutMs?: number; } const DEFAULT_CLI_OPTIONS = { - timeoutMs: 15_000, + timeoutMs: 15_000, }; /** @@ -111,60 +111,58 @@ const DEFAULT_CLI_OPTIONS = { * @returns Command object for handling in client code. */ export const runCommand = ( - command: string, - args: string[] = [], - options?: CliOptions, + command: string, + args: string[] = [], + options?: CliOptions, ): AsyncCommand => { - const optionsWithDefaults = { ...DEFAULT_CLI_OPTIONS, ...options }; - const process = spawn(command, args, { - ...optionsWithDefaults, - stdio: "pipe", - }); - const complete = new Promise((resolve, reject) => { - let threwError = false; + const optionsWithDefaults = { ...DEFAULT_CLI_OPTIONS, ...options }; + const process = spawn(command, args, { + ...optionsWithDefaults, + stdio: "pipe", + }); + const complete = new Promise((resolve, reject) => { + let threwError = false; - let stdout = ""; - process.stdout.on("data", (data) => { - stdout += data.toString(); - }); - process.stderr.on("data", (data) => { - threwError = true; - process.kill(); - reject(new Error(`command output to stderr: ${data.toString()}`)); - }); + let stdout = ""; + process.stdout.on("data", (data) => { + stdout += data.toString(); + }); + process.stderr.on("data", (data) => { + threwError = true; + process.kill(); + reject(new Error(`command output to stderr: ${data.toString()}`)); + }); - const timer = setTimeout(() => { - threwError = true; - process.kill(); - reject( - new Error( - `max timeout of ${optionsWithDefaults.timeoutMs}ms reached`, - ), - ); - }, optionsWithDefaults.timeoutMs); - process.on("exit", (code) => { - if (threwError) { - return; - } - clearTimeout(timer); - if (code !== null && code !== 0) { - reject(new Error(`command exited with non-zero code: ${code}`)); - return; - } - resolve(stdout); - }); - process.on("error", (error) => { - clearTimeout(timer); - if (!threwError) { - reject(new Error(`command errored: ${error}`)); - threwError = true; - } - }); - }); - return { - complete, - process, - }; + const timer = setTimeout(() => { + threwError = true; + process.kill(); + reject( + new Error(`max timeout of ${optionsWithDefaults.timeoutMs}ms reached`), + ); + }, optionsWithDefaults.timeoutMs); + process.on("exit", (code) => { + if (threwError) { + return; + } + clearTimeout(timer); + if (code !== null && code !== 0) { + reject(new Error(`command exited with non-zero code: ${code}`)); + return; + } + resolve(stdout); + }); + process.on("error", (error) => { + clearTimeout(timer); + if (!threwError) { + reject(new Error(`command errored: ${error}`)); + threwError = true; + } + }); + }); + return { + complete, + process, + }; }; export const npmCmd = os.platform() === "win32" ? "npm.cmd" : "npm"; diff --git a/test/lib/expect.ts b/test/lib/expect.ts index 1a4bd8e..8d6dd41 100644 --- a/test/lib/expect.ts +++ b/test/lib/expect.ts @@ -6,13 +6,13 @@ import { areEqual, displayValue, matches } from "./utils"; class ExpectError extends Error { - public constructor(reason: string, expected: unknown, actual: unknown) { - super( - `${reason}\n` + - `\texpected: ${displayValue(expected)}\n` + - `\tactual : ${displayValue(actual)}`, - ); - } + public constructor(reason: string, expected: unknown, actual: unknown) { + super( + `${reason}\n` + + `\texpected: ${displayValue(expected)}\n` + + `\tactual : ${displayValue(actual)}`, + ); + } } /** @@ -24,138 +24,134 @@ class ExpectError extends Error { * Expect. */ export class Expect { - protected readonly value: T; + protected readonly value: T; - /** - * Create a new expectation around a value. - * - * @param value Value to place assertions upon. - */ - public constructor(value: T) { - this.value = value; - } + /** + * Create a new expectation around a value. + * + * @param value Value to place assertions upon. + */ + public constructor(value: T) { + this.value = value; + } - /** - * Expect the value to equal an expected value. - * - * Note that strict equality checking is used for primitives and structural - * equality is used for objects. - * - * @param expected Expected value. - * - * @throws ExpectError If the actual value does not equal the expected value. - */ - public toEqual(expected: T): void { - if (!areEqual(this.value, expected)) { - throw new ExpectError( - `value does not equal expected`, - expected, - this.value, - ); - } - } + /** + * Expect the value to equal an expected value. + * + * Note that strict equality checking is used for primitives and structural + * equality is used for objects. + * + * @param expected Expected value. + * + * @throws ExpectError If the actual value does not equal the expected value. + */ + public toEqual(expected: T): void { + if (!areEqual(this.value, expected)) { + throw new ExpectError( + "value does not equal expected", + expected, + this.value, + ); + } + } } /** * String-specific Expect assertions. */ export class StringExpect extends Expect { - /** - * Expect the string value to match a RegExp pattern. - * - * @param pattern Regular expression to match against. - * - * @throws ExpectError If the actual value does not match the expected - * RegExp pattern. - */ - public toMatch(pattern: RegExp): void { - if (!this.value.match(pattern)) { - throw new ExpectError( - `value does not match expected pattern`, - pattern, - this.value, - ); - } - } + /** + * Expect the string value to match a RegExp pattern. + * + * @param pattern Regular expression to match against. + * + * @throws ExpectError If the actual value does not match the expected + * RegExp pattern. + */ + public toMatch(pattern: RegExp): void { + if (!this.value.match(pattern)) { + throw new ExpectError( + "value does not match expected pattern", + pattern, + this.value, + ); + } + } - /** - * Expect the string value to start with a particular prefix. - * - * @param prefix Prefix that the string is expected to start with. - * - * @throws ExpectError If the actual value does not start with the expected - * prefix. - */ - public toStartWith(prefix: string): void { - if (!this.value.startsWith(prefix)) { - throw new ExpectError( - `value does not start with expected prefix`, - prefix, - this.value, - ); - } - } + /** + * Expect the string value to start with a particular prefix. + * + * @param prefix Prefix that the string is expected to start with. + * + * @throws ExpectError If the actual value does not start with the expected + * prefix. + */ + public toStartWith(prefix: string): void { + if (!this.value.startsWith(prefix)) { + throw new ExpectError( + "value does not start with expected prefix", + prefix, + this.value, + ); + } + } - /** - * Expect the string value to end with a particular suffix. - * - * @param suffix Suffix that the string is expected to end with. - * - * @throws ExpectError If the actual value does not end with the expected - * suffix. - */ - public toEndWith(suffix: string): void { - if (!this.value.endsWith(suffix)) { - throw new ExpectError( - `value does not end with expected suffix`, - suffix, - this.value, - ); - } - } + /** + * Expect the string value to end with a particular suffix. + * + * @param suffix Suffix that the string is expected to end with. + * + * @throws ExpectError If the actual value does not end with the expected + * suffix. + */ + public toEndWith(suffix: string): void { + if (!this.value.endsWith(suffix)) { + throw new ExpectError( + "value does not end with expected suffix", + suffix, + this.value, + ); + } + } } /** * Function-specific Expect assertions. */ export class FunctionExpect extends Expect<() => T> { - /** - * Expect the function to throw an Error with error message matching a - * string or pattern. - * - * @param pattern String that exactly matches the error message or RegExp - * that should match the error message. - * - * @throws ExpectError If the function does not throw an error, throws a - * non-Error value, or throws an Error whose message does not match - * the expected pattern. - */ - public toThrowErrorMatching(pattern: string | RegExp): void { - try { - this.value(); - } catch (error) { - if (!(error instanceof Error)) { - throw new ExpectError( - `function threw non-Error value`, - pattern, - error, - ); - } - if (!matches(error.message, pattern)) { - throw new ExpectError( - `thrown Error's message does not match pattern`, - pattern, - error.message, - ); - } - return; - } - throw new ExpectError( - `function did not throw expected error`, - pattern, - null, - ); - } + /** + * Expect the function to throw an Error with error message matching a + * string or pattern. + * + * @param pattern String that exactly matches the error message or RegExp + * that should match the error message. + * + * @throws ExpectError If the function does not throw an error, throws a + * non-Error value, or throws an Error whose message does not match + * the expected pattern. + */ + public toThrowErrorMatching(pattern: string | RegExp): void { + try { + this.value(); + } catch (error) { + if (!(error instanceof Error)) { + throw new ExpectError("function threw non-Error value", pattern, error); + } + if (!matches(error.message, pattern)) { + throw new ExpectError( + `thrown Error's message does not match pattern`, + pattern, + error.message, + ); + } + return; + } + throw new ExpectError( + "function did not throw expected error", + pattern, + null, + ); + } } /** @@ -202,11 +198,11 @@ export function expect(fn: () => T): FunctionExpect; * @param value Value to place expectations upon. */ export function expect(value: unknown): Expect { - if (typeof value === "string") { - return new StringExpect(value); - } - if (typeof value === "function") { - return new FunctionExpect(value as () => unknown); - } - return new Expect(value); + if (typeof value === "string") { + return new StringExpect(value); + } + if (typeof value === "function") { + return new FunctionExpect(value as () => unknown); + } + return new Expect(value); } diff --git a/test/lib/harness.ts b/test/lib/harness.ts index 57034c9..d371e39 100644 --- a/test/lib/harness.ts +++ b/test/lib/harness.ts @@ -7,68 +7,66 @@ import { expect } from "./expect"; import { displayValue, shuffle } from "./utils"; interface Test { - readonly name: string; + readonly name: string; - runTest(): void | Promise; + runTest(): void | Promise; } type TestResult = { - testName: string; + testName: string; } & ( - | { - result: "pass"; - } - | { - result: "fail"; - error: Error; - } + | { + result: "pass"; + } + | { + result: "fail"; + error: Error; + } ); const runTest = async (test: Test): Promise => { - let result: TestResult; - try { - await test.runTest(); - result = { - testName: test.name, - result: "pass", - }; - } catch (error) { - result = { - testName: test.name, - result: "fail", - error: - error instanceof Error - ? error - : new Error( - `threw non-error object: ${displayValue(error)}`, - ), - }; - } - return result; + let result: TestResult; + try { + await test.runTest(); + result = { + testName: test.name, + result: "pass", + }; + } catch (error) { + result = { + testName: test.name, + result: "fail", + error: + error instanceof Error + ? error + : new Error(`threw non-error object: ${displayValue(error)}`), + }; + } + return result; }; /** * Context object that is passed into a test suite definition. */ export interface TestSuiteContext { - /** - * Define a test in this test suite. - * - * Tests are functions that pass if they are executed and don't throw (or - * that resolve for async tests), and that fail if they throw an error (or - * reject for async tests). - * - * Note that tests are executed in a random order within a test suite in - * order to prevent accidentally creating order dependencies between tests, - * which can result in brittle tests and is a code smell that might indicate - * that the code under test is also brittle. - */ - test: (name: string, def: () => void | Promise) => void; - /** - * Expectation builder function used to build human-readable assertions and - * errors. - */ - expect: typeof expect; + /** + * Define a test in this test suite. + * + * Tests are functions that pass if they are executed and don't throw (or + * that resolve for async tests), and that fail if they throw an error (or + * reject for async tests). + * + * Note that tests are executed in a random order within a test suite in + * order to prevent accidentally creating order dependencies between tests, + * which can result in brittle tests and is a code smell that might indicate + * that the code under test is also brittle. + */ + test: (name: string, def: () => void | Promise) => void; + /** + * Expectation builder function used to build human-readable assertions and + * errors. + */ + expect: typeof expect; } /** @@ -85,36 +83,36 @@ export interface TestSuiteContext { * @param def Function used to declare the tests */ export const testSuite = ( - suiteName: string, - def: (ctx: TestSuiteContext) => void, + suiteName: string, + def: (ctx: TestSuiteContext) => void, ): void => { - const tests: Test[] = []; - const test = (name: string, runTest: () => void | Promise): void => { - tests.push({ name, runTest }); - }; - def({ test, expect }); + const tests: Test[] = []; + const test = (name: string, runTest: () => void | Promise): void => { + tests.push({ name, runTest }); + }; + def({ test, expect }); - // Randomly shuffle the tests so that we can catch accidental order - // dependencies. - shuffle(tests); - (async () => { - const results = await Promise.all(tests.map((test) => runTest(test))); - let passed = 0; - for (const testResult of results) { - if (testResult.result === "fail") { - console.error( - `[TEST FAILURE] "${suiteName}": "${testResult.testName}": ` + - `${testResult.error.stack}\n`, - ); - continue; - } - passed += 1; - } - console.info( - `[TEST] suite "${suiteName}": ${passed} of ${tests.length} succeeded\n\n`, - ); - if (passed < tests.length) { - process.exitCode = 1; - } - })(); + // Randomly shuffle the tests so that we can catch accidental order + // dependencies. + shuffle(tests); + (async () => { + const results = await Promise.all(tests.map((test) => runTest(test))); + let passed = 0; + for (const testResult of results) { + if (testResult.result === "fail") { + console.error( + `[TEST FAILURE] "${suiteName}": "${testResult.testName}": ` + + `${testResult.error.stack}\n`, + ); + continue; + } + passed += 1; + } + console.info( + `[TEST] suite "${suiteName}": ${passed} of ${tests.length} succeeded\n\n`, + ); + if (passed < tests.length) { + process.exitCode = 1; + } + })(); }; diff --git a/test/lib/utils.ts b/test/lib/utils.ts index 76896c5..2c77e1c 100644 --- a/test/lib/utils.ts +++ b/test/lib/utils.ts @@ -9,43 +9,43 @@ * @param arr Array to shuffle. */ export const shuffle = (arr: T[]): void => { - let j: number; - let x: T; - for (let i = arr.length - 1; i > 0; i--) { - j = Math.floor(Math.random() * (i + 1)); - x = arr[i]; - arr[i] = arr[j]; - arr[j] = x; - } + let j: number; + let x: T; + for (let i = arr.length - 1; i > 0; i--) { + j = Math.floor(Math.random() * (i + 1)); + x = arr[i]; + arr[i] = arr[j]; + arr[j] = x; + } }; const areArraysEqual = (a: T[], b: T[]): boolean => { - if (a.length != b.length) { - return false; - } - for (let i = 0; i < a.length; i++) { - if (!areEqual(a[i], b[i])) { - return false; - } - } - return true; + if (a.length !== b.length) { + return false; + } + for (let i = 0; i < a.length; i++) { + if (!areEqual(a[i], b[i])) { + return false; + } + } + return true; }; const areObjectsEqual = >( - a: T, - b: T, + a: T, + b: T, ): boolean => { - const aKeys = Object.keys(a) as Array; - const bKeys = Object.keys(b) as Array; - if (aKeys.length !== bKeys.length) { - return false; - } - for (const key of aKeys) { - if (!areEqual(a[key], b[key])) { - return false; - } - } - return true; + const aKeys = Object.keys(a) as Array; + const bKeys = Object.keys(b) as Array; + if (aKeys.length !== bKeys.length) { + return false; + } + for (const key of aKeys) { + if (!areEqual(a[key], b[key])) { + return false; + } + } + return true; }; /** @@ -58,19 +58,19 @@ const areObjectsEqual = >( * @return Whether the two values are structurally equal. */ export const areEqual = (a: T, b: T): boolean => { - if (Array.isArray(a) && Array.isArray(b)) { - return areArraysEqual(a, b); - } - if (a instanceof RegExp && b instanceof RegExp) { - return a.source === b.source; - } - if (typeof a === "object" && typeof b === "object") { - return areObjectsEqual( - a as Record, - b as Record, - ); - } - return a === b; + if (Array.isArray(a) && Array.isArray(b)) { + return areArraysEqual(a, b); + } + if (a instanceof RegExp && b instanceof RegExp) { + return a.source === b.source; + } + if (typeof a === "object" && typeof b === "object") { + return areObjectsEqual( + a as Record, + b as Record, + ); + } + return a === b; }; /** @@ -84,10 +84,10 @@ export const areEqual = (a: T, b: T): boolean => { * @param pattern String or RegExp pattern to match value against. */ export const matches = (value: string, pattern: string | RegExp): boolean => { - if (typeof pattern === "string") { - return value === pattern; - } - return pattern.test(value); + if (typeof pattern === "string") { + return value === pattern; + } + return pattern.test(value); }; /** @@ -102,11 +102,11 @@ export const matches = (value: string, pattern: string | RegExp): boolean => { * @return Rendered value to display. */ export const displayValue = (value: unknown): string => { - if (value === undefined) { - return "undefined"; - } - if (value instanceof RegExp) { - return value.toString(); - } - return JSON.stringify(value); + if (value === undefined) { + return "undefined"; + } + if (value instanceof RegExp) { + return value.toString(); + } + return JSON.stringify(value); }; diff --git a/test/run-e2e.ts b/test/run-e2e.ts index 31a7c8a..1fdfc96 100644 --- a/test/run-e2e.ts +++ b/test/run-e2e.ts @@ -3,9 +3,9 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { fork } from "child_process"; -import * as fs from "fs"; -import * as path from "path"; +import { fork } from "node:child_process"; +import * as fs from "node:fs"; +import * as path from "node:path"; import { shuffle } from "./lib/utils"; @@ -14,10 +14,10 @@ const files = fs.readdirSync(TEST_SUITES_DIR); // Shuffle test suites to detect ordering dependencies between them. shuffle(files); for (const file of files) { - const fullPath = path.join(TEST_SUITES_DIR, file); - fork(path.relative(process.cwd(), fullPath)).on("exit", (code) => { - if (code !== 0) { - process.exitCode = 1; - } - }); + const fullPath = path.join(TEST_SUITES_DIR, file); + fork(path.relative(process.cwd(), fullPath)).on("exit", (code) => { + if (code !== 0) { + process.exitCode = 1; + } + }); } diff --git a/test/run-tests.ts b/test/run-tests.ts index f838fb7..a928ed2 100644 --- a/test/run-tests.ts +++ b/test/run-tests.ts @@ -3,9 +3,9 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { fork } from "child_process"; -import * as fs from "fs"; -import * as path from "path"; +import { fork } from "node:child_process"; +import * as fs from "node:fs"; +import * as path from "node:path"; import { shuffle } from "./lib/utils"; @@ -14,10 +14,10 @@ const files = fs.readdirSync(TEST_SUITES_DIR); // Shuffle test suites to detect ordering dependencies between them. shuffle(files); for (const file of files) { - const fullPath = path.join(TEST_SUITES_DIR, file); - fork(path.relative(process.cwd(), fullPath)).on("exit", (code) => { - if (code !== 0) { - process.exitCode = 1; - } - }); + const fullPath = path.join(TEST_SUITES_DIR, file); + fork(path.relative(process.cwd(), fullPath)).on("exit", (code) => { + if (code !== 0) { + process.exitCode = 1; + } + }); } diff --git a/test/test-suites/rendering.tsx b/test/test-suites/rendering.tsx index ed3dfe5..e9a54bf 100644 --- a/test/test-suites/rendering.tsx +++ b/test/test-suites/rendering.tsx @@ -3,151 +3,150 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { Component, createElement, Fragment } from "../../dist"; +import { type Component, Fragment, createElement } from "../../dist"; import { renderPage } from "../../dist/render"; import { testSuite } from "../lib"; testSuite("renderPage", ({ test, expect }) => { - test("throws an Error when root elem is not html tag", () => { - expect(() => renderPage(

)).toThrowErrorMatching( - "attempted to render page with non-HTML root element div", - ); - }); + test("throws an Error when root elem is not html tag", () => { + expect(() => renderPage(
)).toThrowErrorMatching( + "attempted to render page with non-HTML root element div", + ); + }); - test("outputs a HTML5 DOCTYPE declaration", () => { - const html = renderPage(); - expect(html).toStartWith(""); - }); + test("outputs a HTML5 DOCTYPE declaration", () => { + const html = renderPage(); + expect(html).toStartWith(""); + }); - test("escapes HTML in tag names", () => { - const html = renderPage( - {createElement("div>, - ); - expect(html).toEqual( - "", - ); - }); + test("escapes HTML in tag names", () => { + const html = renderPage({createElement("div>); + expect(html).toEqual( + "", + ); + }); - test("renders html attributes", () => { - const html = renderPage( - -
- , - ); - expect(html).toEqual( - '
', - ); - }); + test("renders html attributes", () => { + const html = renderPage( + +
+ , + ); + expect(html).toEqual( + '
', + ); + }); - test("renders common html tags", () => { - const html = renderPage( - - - - </head> - <body> - <div /> - </body> - </html>, - ); - expect(html).toEqual( - "<!DOCTYPE html><html><head><title>
", - ); - }); + test("renders common html tags", () => { + const html = renderPage( + + + + </head> + <body> + <div /> + </body> + </html>, + ); + expect(html).toEqual( + "<!DOCTYPE html><html><head><title>
", + ); + }); - test("renders text nodes", () => { - const html = renderPage(There are three lights!); - expect(html).toEqual( - "There are three lights!", - ); - }); + test("renders text nodes", () => { + const html = renderPage(There are three lights!); + expect(html).toEqual("There are three lights!"); + }); - test("renders spliced number nodes", () => { - const nLights = 3; - const html = renderPage(There are {nLights} lights!); - expect(html).toEqual("There are 3 lights!"); - }); + test("renders spliced number nodes", () => { + const nLights = 3; + const html = renderPage(There are {nLights} lights!); + expect(html).toEqual("There are 3 lights!"); + }); - test("renders spliced arrays", () => { - const Light: Component<{ lightN: number }> = ({ lightN }) => ( -
{lightN}
- ); - const lights = [1, 2, 3]; - const html = renderPage( - - There are{" "} - {lights.map((lightN) => ( - - ))}{" "} - lights! - , - ); - expect(html).toEqual( - "There are
1
2
3
lights!", - ); - }); + test("renders spliced arrays", () => { + const Light: Component<{ lightN: number }> = ({ lightN }) => ( +
{lightN}
+ ); + const lights = [1, 2, 3]; + const html = renderPage( + + There are{" "} + {lights.map((lightN) => ( + + ))}{" "} + lights! + , + ); + expect(html).toEqual( + "There are
1
2
3
lights!", + ); + }); - test("renders components w/ custom properties", () => { - interface LightProps { - nLights: number; - } - const Light: Component = ({ nLights }) => ( -
{nLights} lights
- ); - const html = renderPage( - - There are ! - , - ); - expect(html).toEqual( - "There are
3 lights
!", - ); - }); + test("renders components w/ custom properties", () => { + interface LightProps { + nLights: number; + } + const Light: Component = ({ nLights }) => ( +
{nLights} lights
+ ); + const html = renderPage( + + There are ! + , + ); + expect(html).toEqual( + "There are
3 lights
!", + ); + }); - test("renders fragment children only", () => { - const html = renderPage( - - -
test of
-
fragments
-
- , - ); - expect(html).toEqual( - "
test of
fragments
", - ); - }); + test("renders fragment children only", () => { + const html = renderPage( + + +
test of
+
fragments
+
+ , + ); + expect(html).toEqual( + "
test of
fragments
", + ); + }); - test("renders unescaped HTML via dangerouslySetInnerHTML", () => { - const html = renderPage( - -
red alert!
", - }} - /> - , - ); - expect(html).toEqual( - "
red alert!
", - ); - }); + test("renders unescaped HTML via dangerouslySetInnerHTML", () => { + const html = renderPage( + +
red alert!
", + }} + /> + , + ); + expect(html).toEqual( + "
red alert!
", + ); + }); - test("throws error when both dangerouslySetInnerHTML and children prop present", () => { - expect(() => - renderPage( - -
set phasers to kill
", - }} - > -
set phasers to stun
-
- , - ), - ).toThrowErrorMatching( - 'An element with children may not have a "dangerouslySetInnerHTML" prop since children would be overriden', - ); - }); + test("throws error when both dangerouslySetInnerHTML and children prop present", () => { + expect(() => + renderPage( + +
set phasers to kill
", + }} + > +
set phasers to stun
+
+ , + ), + ).toThrowErrorMatching( + 'An element with children may not have a "dangerouslySetInnerHTML" prop since children would be overriden', + ); + }); }); diff --git a/test/tsconfig.json b/test/tsconfig.json index e6edc8b..6996e0f 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -1,7 +1,7 @@ { - "extends": "../tsconfig-base.json", - "compilerOptions": { - "jsx": "react", - "jsxFactory": "createElement" - } + "extends": "../tsconfig-base.json", + "compilerOptions": { + "jsx": "react", + "jsxFactory": "createElement" + } } diff --git a/tsconfig-base.json b/tsconfig-base.json index fa9f3df..c4a0bb4 100644 --- a/tsconfig-base.json +++ b/tsconfig-base.json @@ -1,13 +1,13 @@ { - "compilerOptions": { - "module": "CommonJS", - "moduleResolution": "node", - "target": "ES2018", - "lib": ["ES2018"], - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - } + "compilerOptions": { + "module": "CommonJS", + "moduleResolution": "node", + "target": "ES2018", + "lib": ["ES2018"], + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + } } diff --git a/tsconfig.json b/tsconfig.json index 10006e4..0b67cbd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,9 @@ { - "extends": "./tsconfig-base.json", - "compilerOptions": { - "declaration": true, - "sourceMap": true, - "outDir": "./dist" - }, - "include": ["src/**/*.ts"] + "extends": "./tsconfig-base.json", + "compilerOptions": { + "declaration": true, + "sourceMap": true, + "outDir": "./dist" + }, + "include": ["src/**/*.ts"] }