diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..4a6ee7aa
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,12 @@
+node_modules/
+
+server/test/
+client/
+!client/dist/
+
+.*
+README.md
+LICENSE
+nano-staged.json
+simple-git-hooks.json
+Dockerfile
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..8ac1a531
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.svg]
+insert_final_newline = false
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 00000000..849ddff3
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+dist/
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 00000000..318fa10b
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,3 @@
+{
+ "extends": "@logux/eslint-config/esm"
+}
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 152f44c9..00000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "root": true,
- "plugins": [
- "eslint-plugin-github"
- ],
- "env": {
- "es6": true,
- "node": true
- },
- "extends": [
- "plugin:github/recommended",
- "plugin:github/es6"
- ],
- "rules": {
- "eslint-comments/no-use": "off"
- }
-}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..0ee30b10
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,165 @@
+name: CI
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+env:
+ FORCE_COLOR: 2
+jobs:
+
+ test:
+ name: Test
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the repository
+ uses: actions/checkout@v3
+ - name: Install asdf
+ uses: asdf-vm/actions/setup@v1
+ - name: Cache asdf
+ id: asdf-cache
+ uses: actions/cache@v3
+ with:
+ path: ~/.asdf
+ key: asdf-${{ hashFiles('**/.tool-versions') }}
+ - name: Install asdf tools
+ if: steps.asdf-cache.outputs.cache-hit != 'true'
+ uses: asdf-vm/actions/install@v1
+ - name: Cache pnpm modules
+ uses: actions/cache@v3
+ env:
+ cache-name: cache-pnpm-modules
+ with:
+ path: ~/.local/share/pnpm/
+ key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile --ignore-scripts
+ - name: Build regions
+ run: pnpm -r build:regions
+ - name: Run tests
+ run: pnpm test
+
+ deploy:
+ name: Deploy
+ runs-on: ubuntu-latest
+ if: github.ref == 'refs/heads/main'
+ steps:
+ - name: Notify about new deployment
+ uses: bobheadxi/deployments@v1
+ id: deployment
+ with:
+ step: start
+ token: ${{ secrets.GITHUB_TOKEN }}
+ env: production
+ - name: Checkout the repository
+ uses: actions/checkout@v3
+ - name: Install asdf
+ uses: asdf-vm/actions/setup@v1
+ - name: Cache asdf
+ id: asdf-cache
+ uses: actions/cache@v3
+ with:
+ path: ~/.asdf
+ key: asdf-${{ hashFiles('**/.tool-versions') }}
+ - name: Cache pnpm modules
+ uses: actions/cache@v3
+ env:
+ cache-name: cache-pnpm-modules
+ with:
+ path: ~/.local/share/pnpm/
+ key: pnpm-production-${{ hashFiles('pnpm-lock.yaml') }}
+ - name: Install production dependencies
+ run: pnpm install --prod --frozen-lockfile --ignore-scripts
+ - name: Build regions
+ run: pnpm -r build:regions
+ - name: Build static files
+ run: pnpm build
+ - name: Auth Google Cloud
+ uses: google-github-actions/auth@v0
+ with:
+ credentials_json: ${{ secrets.GCLOUD_AUTH }}
+ - name: Install Google Cloud
+ uses: google-github-actions/setup-gcloud@v0
+ - name: Deploy files
+ id: deploy
+ run: ./node_modules/.bin/ssdeploy deploy --verbose
+ env:
+ GCLOUD_APP: ${{ secrets.GCLOUD_APP }}
+ GCLOUD_PROJECT: ${{ secrets.GCLOUD_PROJECT }}
+ CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }}
+ CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
+ - name: Update deployment status
+ uses: bobheadxi/deployments@v1
+ if: always()
+ with:
+ step: finish
+ token: ${{ secrets.GITHUB_TOKEN }}
+ status: ${{ job.status }}
+ env: ${{ steps.deployment.outputs.env }}
+ env_url: ${{ steps.deploy.outputs.url }}
+ deployment_id: ${{ steps.deployment.outputs.deployment_id }}
+
+ preview:
+ name: Preview
+ runs-on: ubuntu-latest
+ if: github.ref != 'refs/heads/main'
+ steps:
+ - name: Notify about new deployment
+ uses: bobheadxi/deployments@v1
+ id: deployment
+ with:
+ step: start
+ token: ${{ secrets.GITHUB_TOKEN }}
+ ref: ${{ github.head_ref }}
+ env: preview-${{ github.event.number }}
+ - name: Checkout the repository
+ uses: actions/checkout@v3
+ - name: Install asdf
+ uses: asdf-vm/actions/setup@v1
+ - name: Cache asdf
+ id: asdf-cache
+ uses: actions/cache@v3
+ with:
+ path: ~/.asdf
+ key: asdf-${{ hashFiles('**/.tool-versions') }}
+ - name: Install asdf tools
+ if: steps.asdf-cache.outputs.cache-hit != 'true'
+ uses: asdf-vm/actions/install@v1
+ - name: Cache pnpm modules
+ uses: actions/cache@v3
+ env:
+ cache-name: cache-pnpm-modules
+ with:
+ path: ~/.local/share/pnpm/
+ key: pnpm-production-${{ hashFiles('pnpm-lock.yaml') }}
+ - name: Install production dependencies
+ run: pnpm install --prod --frozen-lockfile --ignore-scripts
+ - name: Build regions
+ run: pnpm -r build:regions
+ - name: Build static files
+ run: pnpm build
+ - name: Auth Google Cloud
+ uses: google-github-actions/auth@v0
+ with:
+ credentials_json: ${{ secrets.GCLOUD_AUTH }}
+ - name: Install Google Cloud
+ uses: google-github-actions/setup-gcloud@v0
+ - name: Deploy files
+ id: deploy
+ run: ./node_modules/.bin/ssdeploy preview $PR --verbose
+ env:
+ PR: ${{ github.event.number }}
+ GCLOUD_APP: ${{ secrets.GCLOUD_APP }}
+ GCLOUD_PROJECT: ${{ secrets.GCLOUD_PROJECT }}
+ CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }}
+ CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
+ - name: Update deployment status
+ uses: bobheadxi/deployments@v1
+ if: always()
+ with:
+ step: finish
+ token: ${{ secrets.GITHUB_TOKEN }}
+ status: ${{ job.status }}
+ env: ${{ steps.deployment.outputs.env }}
+ env_url: ${{ steps.deploy.outputs.url }}
+ deployment_id: ${{ steps.deployment.outputs.deployment_id }}
diff --git a/.github/workflows/close.yml b/.github/workflows/close.yml
new file mode 100644
index 00000000..3c303695
--- /dev/null
+++ b/.github/workflows/close.yml
@@ -0,0 +1,50 @@
+name: Clean Preview
+on:
+ pull_request:
+ types: [ closed ]
+jobs:
+ close:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Clean from GitHub
+ uses: bobheadxi/deployments@v1
+ with:
+ step: delete-env
+ token: ${{ secrets.GITHUB_TOKEN }}
+ env: preview-${{ github.event.number }}
+ - name: Checkout the repository
+ uses: actions/checkout@v3
+ - name: Install asdf
+ uses: asdf-vm/actions/setup@v1
+ - name: Cache asdf
+ id: asdf-cache
+ uses: actions/cache@v3
+ with:
+ path: ~/.asdf
+ key: asdf-${{ hashFiles('**/.tool-versions') }}
+ - name: Install asdf tools
+ if: steps.asdf-cache.outputs.cache-hit != 'true'
+ uses: asdf-vm/actions/install@v1
+ - name: Cache pnpm modules
+ uses: actions/cache@v3
+ env:
+ cache-name: cache-pnpm-modules
+ with:
+ path: ~/.local/share/pnpm/
+ key: pnpm-production-${{ hashFiles('pnpm-lock.yaml') }}
+ - name: Install dependencies
+ run: pnpm install --prod --frozen-lockfile --ignore-scripts
+ - name: Auth Google Cloud
+ uses: google-github-actions/auth@v0
+ with:
+ credentials_json: ${{ secrets.GCLOUD_AUTH }}
+ - name: Install Google Cloud
+ uses: google-github-actions/setup-gcloud@v0
+ - name: Clean from Google Cloud
+ run: ./node_modules/.bin/ssdeploy close $PR --verbose
+ env:
+ PR: ${{ github.event.number }}
+ GCLOUD_APP: ${{ secrets.GCLOUD_APP }}
+ GCLOUD_PROJECT: ${{ secrets.GCLOUD_PROJECT }}
+ CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }}
+ CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
deleted file mode 100644
index 1d717808..00000000
--- a/.github/workflows/test.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: Tests
-on: [push, pull_request]
-env:
- CI: true
-
-jobs:
- test:
- runs-on: ubuntu-latest
-
- steps:
- - name: Clone repository
- uses: actions/checkout@v1
-
- - name: Set up Node.js
- uses: actions/setup-node@v1
- with:
- node-version: "10"
-
- - run: node --version
- - run: npm --version
-
- - name: Install npm dependencies
- run: npm install
-
- - name: Run tests
- run: npm test
diff --git a/.gitignore b/.gitignore
index 1f53980a..b9470778 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,2 @@
-node_modules
-*.log
-.DS_Store
-package-lock.json
-
-.vercel
+node_modules/
+dist/
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 00000000..82ad122b
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,8 @@
+{
+ "arrowParens": "avoid",
+ "jsxSingleQuote": false,
+ "quoteProps": "consistent",
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "none"
+}
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 00000000..2a65dd33
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,11 @@
+{
+ "extends": "@logux/stylelint-config",
+ "ignoreFiles": ["dist/**/*"],
+ "rules": {
+ "function-disallowed-list": ["rgb", "rgba", "hsl", "hsla"],
+ "alpha-value-notation": "percentage",
+ "color-named": "never",
+ "declaration-block-no-redundant-longhand-properties": null,
+ "font-family-no-duplicate-names": [true, { "ignoreFontFamilyNames":"monospace"}]
+ }
+}
diff --git a/.tool-versions b/.tool-versions
new file mode 100644
index 00000000..86e236dc
--- /dev/null
+++ b/.tool-versions
@@ -0,0 +1,2 @@
+nodejs 18.7.0
+pnpm 7.9.1
diff --git a/CNAME b/CNAME
deleted file mode 100644
index 7480dbbf..00000000
--- a/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-browserl.ist
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..16dd14a2
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,16 @@
+FROM node:18-alpine
+
+ENV NODE_ENV production
+WORKDIR /var/www
+COPY --chown=node:node . /var/www
+
+RUN corepack enable
+RUN corepack prepare pnpm@7.9.1 --activate
+COPY ./pnpm-workspace.yaml /var/www/
+COPY ./package.json /var/www/
+COPY ./pnpm-lock.yaml /var/www/
+COPY ./server/ /var/www/server/
+RUN pnpm install --filter ./server --prod --frozen-lockfile --ignore-scripts
+COPY ./client/dist/ /var/www/client/dist/
+
+CMD "node" "server/index.js"
diff --git a/README.md b/README.md
index 159268d9..2e903b5c 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,43 @@
-# Browserl.ist [![Build Status](https://github.com/browserslist/browserl.ist/workflows/Tests/badge.svg)](https://github.com/browserslist/browserl.ist/actions?workflow=Tests)
+# Browserslist Website
-> A website that shows what browsers supported by a browserslist string
+This website uses [Browserslist] and [Can I Use] to display
+the compatible browsers for a browsers query.
+
+[browserslist]: https://github.com/browserslist/browserslist
+[Can I Use]: https://github.com/Fyrd/caniuse
-This website uses [browserslist][] and [caniuse][] to display the compatible browsers for a [browserslist search query](https://github.com/ai/browserslist#queries).
## Development
-This website runs on [expressjs](https://expressjs.com/). To run locally, after `npm install` to install the dependencies, `npm start` to run the server.
+To run a local copy for development:
+
+1. Install correct versions of Node.js and pnpm. There are two ways:
+ - With [`asdf`](https://github.com/asdf-vm/asdf) version manager:
+
+ ```sh
+ asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git
+ asdf plugin-add pnpm https://github.com/jonathanmorley/asdf-pnpm.git
+ asdf install
+ ```
+
+ - Manually by check versions in `.tool-versions`.
+
+2. Install dependencies:
-## Contributing
+ ```sh
+ pnpm install
+ ```
-I'm open to any pull requests or bug reports. Anything that has to do with the data that is presented should be opened with [browserslist][] or [caniuse][].
+3. Run local server:
-## License
+ - Server with client-side hot-reload
+ ```sh
+ pnpm start
+ ```
-[MIT](./LICENSE) © [Browserslist](https://github.com/browserslist)
+ - Server production mode
+ ```sh
+ pnpm ssdeploy run
+ ```
-[browserslist]: https://github.com/ai/browserslist
-[caniuse]: https://github.com/Fyrd/caniuse
+We recommend to install Prettier and EditorConfig plugins to your text editor.
diff --git a/api/server.js b/api/server.js
deleted file mode 100644
index 0d809f65..00000000
--- a/api/server.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require("../app");
diff --git a/app.js b/app.js
deleted file mode 100644
index 481ffe59..00000000
--- a/app.js
+++ /dev/null
@@ -1,56 +0,0 @@
-"use strict";
-
-const path = require("path");
-const express = require("express");
-const logger = require("morgan");
-const cookieParser = require("cookie-parser");
-const bodyParser = require("body-parser");
-
-const routes = require("./routes/index");
-
-const app = express();
-
-// view engine setup
-app.set("views", path.join(__dirname, "views"));
-app.set("view engine", "pug");
-
-app.use(logger("dev"));
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({ extended: false }));
-app.use(cookieParser());
-app.use(express.static(path.join(__dirname, "public")));
-
-app.use("/", routes);
-
-// catch 404 and forward to error handler
-app.use((req, res, next) => {
- const err = new Error("Not Found");
- err.status = 404;
- next(err);
-});
-
-// error handlers
-
-// development error handler
-// will print stacktrace
-if (app.get("env") === "development") {
- app.use((err, req, res) => {
- res.status(err.status || 500);
- res.render("error", {
- message: err.message,
- error: err,
- });
- });
-}
-
-// production error handler
-// no stacktraces leaked to user
-app.use((err, req, res) => {
- res.status(err.status || 500);
- res.render("error", {
- message: err.message,
- error: {},
- });
-});
-
-module.exports = app;
diff --git a/bin/www b/bin/www
deleted file mode 100755
index 20029c57..00000000
--- a/bin/www
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env node
-
-/* eslint-disable no-console */
-
-"use strict";
-
-/**
- * Module dependencies.
- */
-
-const app = require("../app");
-const debug = require("debug")("browserlist:server");
-const http = require("http");
-
-/**
- * Get port from environment and store in Express.
- */
-
-const PORT = normalizePort(process.env.PORT || "3000");
-app.set("port", PORT);
-
-/**
- * Create HTTP server.
- */
-
-const server = http.createServer(app);
-
-/**
- * Listen on provided port, on all network interfaces.
- */
-
-server.listen(PORT);
-server.on("error", onError);
-server.on("listening", onListening);
-
-/**
- * Normalize a port into a number, string, or false.
- */
-
-function normalizePort(val) {
- const port = parseInt(val, 10);
-
- if (isNaN(port)) {
- // named pipe
- return val;
- }
-
- if (port >= 0) {
- // port number
- return port;
- }
-
- return false;
-}
-
-/**
- * Event listener for HTTP server "error" event.
- */
-
-function onError(error) {
- if (error.syscall !== "listen") {
- throw error;
- }
-
- const bind = typeof PORT === "string" ? `Pipe ${PORT}` : `Port ${PORT}`;
-
- // handle specific listen errors with friendly messages
- switch (error.code) {
- case "EACCES":
- console.error(`${bind} requires elevated privileges`);
- process.exit(1);
- break;
- case "EADDRINUSE":
- console.error(`${bind} is already in use`);
- process.exit(1);
- break;
- default:
- throw error;
- }
-}
-
-/**
- * Event listener for HTTP server "listening" event.
- */
-
-function onListening() {
- const addr = server.address();
- const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`;
- debug(`Listening on ${bind}`);
-}
diff --git a/client/.postcssrc b/client/.postcssrc
new file mode 100644
index 00000000..2747ebea
--- /dev/null
+++ b/client/.postcssrc
@@ -0,0 +1,13 @@
+{
+ "plugins": {
+ "@csstools/postcss-oklab-function": {
+ "subFeatures": {
+ "displayP3": false
+ }
+ },
+ "postcss-opacity-percentage": {},
+ "postcss-nesting": {},
+ "postcss-media-minmax": {},
+ "autoprefixer": {}
+ }
+}
diff --git a/client/.size-limit.json b/client/.size-limit.json
new file mode 100644
index 00000000..f0123cc9
--- /dev/null
+++ b/client/.size-limit.json
@@ -0,0 +1,13 @@
+[
+ {
+ "name": "Files to download",
+ "path": ["dist/**/*", "!dist/*.ico", "!dist/*.webmanifest", "!dist/*.png"],
+ "limit": "40 KB"
+ },
+ {
+ "name": "All scripts to execute",
+ "path": "dist/*.js",
+ "gzip": false,
+ "limit": "15 KB"
+ }
+]
diff --git a/client/data/.gitignore b/client/data/.gitignore
new file mode 100644
index 00000000..469a7907
--- /dev/null
+++ b/client/data/.gitignore
@@ -0,0 +1 @@
+regions.json
diff --git a/client/data/browsers-logos.js b/client/data/browsers-logos.js
new file mode 100644
index 00000000..80283fd7
--- /dev/null
+++ b/client/data/browsers-logos.js
@@ -0,0 +1,21 @@
+/* eslint-disable camelcase */
+export { default as and_chr } from './browsers-logos/and_chr.svg'
+export { default as and_ff } from './browsers-logos/and_ff.svg'
+export { default as and_qq } from './browsers-logos/and_qq.svg'
+export { default as and_uc } from './browsers-logos/and_uc.svg'
+export { default as android } from './browsers-logos/android.svg'
+export { default as baidu } from './browsers-logos/baidu.svg'
+export { default as bb } from './browsers-logos/bb.svg'
+export { default as chrome } from './browsers-logos/chrome.svg'
+export { default as edge } from './browsers-logos/edge.svg'
+export { default as firefox } from './browsers-logos/firefox.svg'
+export { default as ie_mob } from './browsers-logos/ie_mob.svg'
+export { default as ie } from './browsers-logos/ie.svg'
+export { default as ios_saf } from './browsers-logos/ios_saf.svg'
+export { default as kaios } from './browsers-logos/kaios.svg'
+export { default as node } from './browsers-logos/node.svg'
+export { default as op_mini } from './browsers-logos/op_mini.svg'
+export { default as op_mob } from './browsers-logos/op_mob.svg'
+export { default as opera } from './browsers-logos/opera.svg'
+export { default as safari } from './browsers-logos/safari.svg'
+export { default as samsung } from './browsers-logos/samsung.svg'
diff --git a/client/data/browsers-logos/and_chr.svg b/client/data/browsers-logos/and_chr.svg
new file mode 100644
index 00000000..30675815
--- /dev/null
+++ b/client/data/browsers-logos/and_chr.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/and_ff.svg b/client/data/browsers-logos/and_ff.svg
new file mode 100644
index 00000000..98cca08f
--- /dev/null
+++ b/client/data/browsers-logos/and_ff.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/and_qq.svg b/client/data/browsers-logos/and_qq.svg
new file mode 100644
index 00000000..87a23fd9
--- /dev/null
+++ b/client/data/browsers-logos/and_qq.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/and_uc.svg b/client/data/browsers-logos/and_uc.svg
new file mode 100644
index 00000000..4cee13f7
--- /dev/null
+++ b/client/data/browsers-logos/and_uc.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/android.svg b/client/data/browsers-logos/android.svg
new file mode 100644
index 00000000..f4e854e7
--- /dev/null
+++ b/client/data/browsers-logos/android.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/baidu.svg b/client/data/browsers-logos/baidu.svg
new file mode 100644
index 00000000..a8a456d6
--- /dev/null
+++ b/client/data/browsers-logos/baidu.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/bb.svg b/client/data/browsers-logos/bb.svg
new file mode 100644
index 00000000..e784c5fc
--- /dev/null
+++ b/client/data/browsers-logos/bb.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/chrome.svg b/client/data/browsers-logos/chrome.svg
new file mode 100644
index 00000000..30675815
--- /dev/null
+++ b/client/data/browsers-logos/chrome.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/edge.svg b/client/data/browsers-logos/edge.svg
new file mode 100644
index 00000000..9292f223
--- /dev/null
+++ b/client/data/browsers-logos/edge.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/firefox.svg b/client/data/browsers-logos/firefox.svg
new file mode 100644
index 00000000..98cca08f
--- /dev/null
+++ b/client/data/browsers-logos/firefox.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/ie.svg b/client/data/browsers-logos/ie.svg
new file mode 100644
index 00000000..fb684e68
--- /dev/null
+++ b/client/data/browsers-logos/ie.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/ie_mob.svg b/client/data/browsers-logos/ie_mob.svg
new file mode 100644
index 00000000..fb684e68
--- /dev/null
+++ b/client/data/browsers-logos/ie_mob.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/ios_saf.svg b/client/data/browsers-logos/ios_saf.svg
new file mode 100644
index 00000000..e5ece08d
--- /dev/null
+++ b/client/data/browsers-logos/ios_saf.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/kaios.svg b/client/data/browsers-logos/kaios.svg
new file mode 100644
index 00000000..9c88539f
--- /dev/null
+++ b/client/data/browsers-logos/kaios.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/node.svg b/client/data/browsers-logos/node.svg
new file mode 100644
index 00000000..47f791ee
--- /dev/null
+++ b/client/data/browsers-logos/node.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/op_mini.svg b/client/data/browsers-logos/op_mini.svg
new file mode 100644
index 00000000..251b6938
--- /dev/null
+++ b/client/data/browsers-logos/op_mini.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/op_mob.svg b/client/data/browsers-logos/op_mob.svg
new file mode 100644
index 00000000..cf4c44d8
--- /dev/null
+++ b/client/data/browsers-logos/op_mob.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/opera.svg b/client/data/browsers-logos/opera.svg
new file mode 100644
index 00000000..cf4c44d8
--- /dev/null
+++ b/client/data/browsers-logos/opera.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/safari.svg b/client/data/browsers-logos/safari.svg
new file mode 100644
index 00000000..e5ece08d
--- /dev/null
+++ b/client/data/browsers-logos/safari.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/browsers-logos/samsung.svg b/client/data/browsers-logos/samsung.svg
new file mode 100644
index 00000000..3c3e6276
--- /dev/null
+++ b/client/data/browsers-logos/samsung.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/data/regions.js b/client/data/regions.js
new file mode 100644
index 00000000..0e881685
--- /dev/null
+++ b/client/data/regions.js
@@ -0,0 +1,31 @@
+// regions.json is created on `postinstall` step
+import { continents, countryCodes } from './regions.json'
+
+export const DEFAULT_REGION = 'alt-ww'
+
+export const regionList = [...Object.keys(continents), ...countryCodes]
+
+export const regionGroups = {
+ continents: Object.entries(continents).map(([id, name]) => {
+ return {
+ id,
+ name
+ }
+ }),
+ countries: countryCodes.map(id => {
+ return {
+ id,
+ name: getCountryName(id)
+ }
+ })
+}
+
+function getCountryName(id) {
+ let isIntlDisplayNameSupports =
+ 'Intl' in window && 'DisplayNames' in window.Intl
+
+ // Show country `id` instead country fullname for old browsers
+ return isIntlDisplayNameSupports
+ ? new Intl.DisplayNames('en-US', { type: 'region' }).of(id)
+ : id
+}
diff --git a/client/data/wikipedia-links.js b/client/data/wikipedia-links.js
new file mode 100644
index 00000000..0b4572e7
--- /dev/null
+++ b/client/data/wikipedia-links.js
@@ -0,0 +1,30 @@
+const WIKIPEDIA_URL = 'https://en.wikipedia.org/wiki/'
+
+const WIKIPEDIA_LINKS = {
+ and_chr: 'Google_Chrome#Android',
+ and_ff: 'Firefox_for_Android',
+ and_qq: 'Tencent_QQ',
+ and_uc: 'UC_Browser',
+ android: 'List_of_features_in_Android#AndroidBrowser',
+ baidu: 'Baidu_Browser',
+ bb: 'BlackBerry#Software',
+ chrome: 'Google_Chrome',
+ edge: 'Microsoft_Edge',
+ firefox: 'Mozilla_Firefox',
+ ie: 'Internet_Explorer',
+ ie_mob: 'Internet_Explorer_Mobile',
+ ios_saf: 'Safari_(web_browser)',
+ kaios: 'KaiOS',
+ node: 'Node.js',
+ op_mini: 'Opera_Mini',
+ op_mob: 'Opera_Mobile',
+ opera: 'Opera_(web_browser)',
+ safari: 'Safari_(web_browser)',
+ samsung: 'Samsung_Internet'
+}
+
+for (let browser in WIKIPEDIA_LINKS) {
+ WIKIPEDIA_LINKS[browser] = WIKIPEDIA_URL + WIKIPEDIA_LINKS[browser]
+}
+
+export default WIKIPEDIA_LINKS
diff --git a/client/index.css b/client/index.css
new file mode 100644
index 00000000..637115ab
--- /dev/null
+++ b/client/index.css
@@ -0,0 +1,2 @@
+@import "./view/base/index.css";
+@import "./view/base/colors.css";
diff --git a/client/index.html b/client/index.html
new file mode 100644
index 00000000..31a04223
--- /dev/null
+++ b/client/index.html
@@ -0,0 +1,465 @@
+
+
+
+
+
+
+ Browserslist
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Browserslist
+
+
+ 10.5k
+
+
+ 4k
+
+
+ Shared browser and platform compatibility config for popular JavaScript tools,
+ including Autoprefixer, Babel, ESLint, PostCSS, and Webpack
+
+ Supported by
+
+ Evil Martians and
+
+ Cube
+
+
+
+
+ Display compatible browsers
+
+
+
+
+
+
+ How to get started
+
+ defaults
- if you're building a web application for
+ the global audience.
+
+
+ node 18
- if you're building a Node.js application,
+ e.g., for SSR.
+
+ Autoprefixer ,
+ Babel or any of the following libraries will find
+ target browsers automatically, when
+ you add the following to package.json :
+
+
+ "browserslist": [
+ "defaults",
+ "not IE 11",
+ "maintained node versions"
+ ]
+
+
+ Query Syntax
+
+
+
+ You can pick a sound set of versions with the `defaults` query which is a
+ shortcut for
+
+ > 0.5%, last 2 versions, Firefox ESR, not dead
+ . It matches recent versions of popular and supported browsers worldwide and includes
+ Firefox Extended Support Release which is updated roughly annually.
+
+
+ The defaults
query was thoroughly designed by the
+ Browserslist community.
+ It helps promote best practices and avoid common pitfalls.
+
+
+
+
+
+
+ You can pick versions that have more than or less than a certain size of the
+ audience worldwide, in a region, or in a country. You can also use the visitor
+ data of your own website.
+
+
+
+ > 5%
- all versions with > 5% of the audience
+ worldwide.
+
+ >= 5% in US
- same as above but in the US.
+
+ >= 5% in alt-AS
- same as above but in
+ Asia.
+
+
+
+
+
+ You may exclude the most recent versions of all browsers that have been just
+ released. Please always add last …
+ versions
to include them back.
+
+ You can exclude your global audience. Please be careful when narrowing the
+ audience to a region or a country.
+
+ You may include dead
versions. Please consider
+ adding not dead
.
+
+
+
+
+
+ > 5% in my stats
- versions with >
+ 5%
+ of usage
+ within your own audience.
+
+ > 5% in circle-ci stats
-
+ versions with > 5% of usage within the audience data from shareable configuration, available as
+ github.com/circleci/circleci-docs/blob/master/browserslist-stats.json
+
+ cover 99.5%
- the smallest set of popular
+ versions with collective usage over 99.5% of the audience worldwide.
+
+ cover 99.5% in CN
- same as above
+ but in China.
+
+ cover 99.5% in alt-EU
- same
+ as above but in Europe.
+
+
+
+
+
+
+
+
+ You can pick a few recent browser versions.
+
+
+
+
+
+
+ ou might exclude older versions still used by a substantial audience.
+ Please always add > …
to include them back.
+
+ ou may pick dead
browsers like Internet Explorer.
+ Always uselast … versions
+ with `not dead`.
+
+
+
+
+
+
+
+
+
+
+
+
+ You can pick browser versions or a version range of your choice.
+
+
+
+
+
+
+ Make sure that your audience uses specific versions (e.g., in a corporate
+ setting) or that your application is not built to work with specific
+ versions (e.g., it's a bleeding-edge demo project). Please consider using
+ last … versions
+ or > …
to include more versions.
+
+
+
+
+
+
+ ie 6-8
- an inclusive range of Internet
+ Explorer
+ versions.
+
+ Firefox ESR
- the latest Firefox Extended
+ Support Release.
+
+
+
+
+
+
+
+
+ You can pick Node.js versions or a version range of your choice. Useful if you
+ know for sure the runtime configuration of your server-side code.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ You can pick browser versions that fully support features from the Can I Use database. See the
+
+ caniuse-lite repository
+
+ for the full list of features.
+
+
+
+
+
+
+ This query rarely works well on its own. Please consider combining it with other queries.
+
+
+
+
+
+
+
+ You can combine versions matched by multiple queries with or
or ,
; you can
+ intersect them with and
. You can also negate any query with not
if it's
+ not the first one in your list.
+
+
+
+
+
+
+ A query with `not` can't be the left-hand one in the list.
+ A query with not is always joined to the left-hand one with `and`, even if `or` or `,` are used.
+
+
+
+
+
+
+
+
+
+
+
+ You can combine your queries with
+ not dead
+ to exclude dead
browsers, i.e.,
+ browsers without official support or updates for more than 24 months.
+ Right now these include IE 11, IE Mobile 11, BlackBerry 10, BlackBerry 7,
+ Samsung 4, Opera Mobile 12.1, and all versions of Baidu.
+
+
+
+
+
+ Why Browserslist
+ Browserslist helps you keep the right balance between browser compatibility and bundle size.
+ You will cover wider audience and have smaller bundle size.
+
+ What people say about Browserslist
+
+
+
+
+
diff --git a/client/index.js b/client/index.js
new file mode 100644
index 00000000..08eb58b5
--- /dev/null
+++ b/client/index.js
@@ -0,0 +1,2 @@
+import './view/Form/form.js'
+import './view/QueryLink/queryLink.js'
diff --git a/client/package.json b/client/package.json
new file mode 100644
index 00000000..14946161
--- /dev/null
+++ b/client/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "browserl.ist-client",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "start": "vite build --watch",
+ "build": "vite build -m production",
+ "build:regions": "node ./scripts/build-regions.js",
+ "test": "pnpm build && size-limit",
+ "postinstall": "pnpm build:regions"
+ },
+ "dependencies": {
+ "@csstools/postcss-oklab-function": "^1.1.1",
+ "autoprefixer": "^10.4.8",
+ "caniuse-lite": "^1.0.30001375",
+ "jstransformer-markdown-it": "^3.0.0",
+ "postcss": "^8.4.16",
+ "postcss-media-minmax": "^5.0.0",
+ "postcss-nesting": "^10.1.10",
+ "postcss-opacity-percentage": "^1.1.2",
+ "vite": "^3.0.7",
+ "vite-plugin-pug-transformer": "^1.0.2"
+ },
+ "devDependencies": {
+ "@size-limit/file": "^8.0.1",
+ "size-limit": "^8.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+}
diff --git a/client/public/browserslist.webmanifest b/client/public/browserslist.webmanifest
new file mode 100644
index 00000000..5ebb4004
--- /dev/null
+++ b/client/public/browserslist.webmanifest
@@ -0,0 +1,10 @@
+{
+ "name": "Browserslist",
+ "start_url": "/",
+ "display": "standalone",
+ "background_color": "#f6f6f8",
+ "icons": [
+ { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
+ { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
+ ]
+}
diff --git a/client/public/favicon.ico b/client/public/favicon.ico
new file mode 100644
index 00000000..a62e3e65
Binary files /dev/null and b/client/public/favicon.ico differ
diff --git a/client/public/icon-192.png b/client/public/icon-192.png
new file mode 100644
index 00000000..6829b358
Binary files /dev/null and b/client/public/icon-192.png differ
diff --git a/client/public/icon-512.png b/client/public/icon-512.png
new file mode 100644
index 00000000..07cc9124
Binary files /dev/null and b/client/public/icon-512.png differ
diff --git a/client/public/og.png b/client/public/og.png
new file mode 100644
index 00000000..be9ccaa7
Binary files /dev/null and b/client/public/og.png differ
diff --git a/client/scripts/build-regions.js b/client/scripts/build-regions.js
new file mode 100644
index 00000000..4e7e4bff
--- /dev/null
+++ b/client/scripts/build-regions.js
@@ -0,0 +1,34 @@
+import { writeFileSync, readdirSync } from 'node:fs'
+
+const DATA_REGION_FILE = 'data/regions.json'
+const REGIONS_LIST_PATH = './node_modules/caniuse-lite/data/regions'
+
+const regions = {
+ continents: {
+ 'alt-ww': 'Global',
+ 'alt-af': 'Africa',
+ 'alt-an': 'Antarctica',
+ 'alt-as': 'Asia',
+ 'alt-eu': 'Europe',
+ 'alt-na': 'North America',
+ 'alt-oc': 'Oceania',
+ 'alt-sa': 'South America'
+ },
+ countryCodes: getCaniuseCountries()
+}
+
+writeFileSync(DATA_REGION_FILE, JSON.stringify(regions))
+process.stdout.write(
+ `A file "client/${DATA_REGION_FILE}" with regions has been created\n`
+)
+
+function getCaniuseCountries() {
+ let regionCodes = readdirSync(REGIONS_LIST_PATH).map(f => f.split('.js')[0])
+
+ return regionCodes
+ .filter(regionCode => {
+ let isContinentCode = regionCode.includes('alt-')
+ return !isContinentCode
+ })
+ .sort((a, b) => b - a)
+}
diff --git a/client/view/Article/Article.css b/client/view/Article/Article.css
new file mode 100644
index 00000000..87d63139
--- /dev/null
+++ b/client/view/Article/Article.css
@@ -0,0 +1,99 @@
+.Article {
+ box-sizing: border-box;
+ flex-basis: 0;
+ flex-grow: 1;
+ width: 50%;
+ padding: 24px 32px;
+}
+
+.Article--stats {
+ position: fixed;
+ top: 0;
+ /* Hide scrollbar */
+ right: calc(-1 * (100vw - 100%));
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ width: 50%;
+ height: 100vh;
+ max-height: 100vh;
+ overflow-y: scroll;
+ background-color: var(--bg-highlited);
+}
+
+.Article--stats h2 {
+ margin: 0;
+ font-size: 22px;
+ line-height: 26px;
+}
+
+.Article > *:last-child {
+ margin-bottom: 0;
+}
+
+.Article > *:first-child {
+ margin-top: 0;
+}
+
+.Article__h1 {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ margin: 0;
+}
+
+.Article__h2 {
+ margin-top: 32px;
+ font-size: 22px;
+ line-height: 26px;
+}
+
+.Article--intro__about {
+ margin: 16px 0;
+ font-size: 25px;
+ line-height: 32px;
+ letter-spacing: 0.01em;
+}
+
+.Article--intro__supported {
+ font-size: 14px;
+ line-height: 20px;
+ color: var(--text-secondary);
+ letter-spacing: 0.02em;
+}
+
+.Article--intro__supported img {
+ height: 16px;
+ vertical-align: middle;
+}
+
+.Article--intro__header {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ align-items: center;
+}
+
+@media (max-width: 740px) {
+ .Article {
+ width: initial;
+ }
+
+ .Article--stats {
+ position: initial;
+ height: initial;
+ max-height: initial;
+ overflow: visible;
+ }
+}
+
+@media (max-width: 460px) {
+ .Article {
+ padding: 16px 24px;
+ }
+
+ .Article--intro__about {
+ font-size: 16px;
+ line-height: 22px;
+ }
+}
diff --git a/client/view/Article/browserlist_logo.svg b/client/view/Article/browserlist_logo.svg
new file mode 100644
index 00000000..2ff11a55
--- /dev/null
+++ b/client/view/Article/browserlist_logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/Article/cube_logo.svg b/client/view/Article/cube_logo.svg
new file mode 100644
index 00000000..7f2333e3
--- /dev/null
+++ b/client/view/Article/cube_logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/Article/evil_maritians_logo.svg b/client/view/Article/evil_maritians_logo.svg
new file mode 100644
index 00000000..9a7e9f96
--- /dev/null
+++ b/client/view/Article/evil_maritians_logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/Badge/Badge.css b/client/view/Badge/Badge.css
new file mode 100644
index 00000000..8bce01c8
--- /dev/null
+++ b/client/view/Badge/Badge.css
@@ -0,0 +1,19 @@
+.Badge {
+ display: flex;
+ gap: 4px;
+ align-items: center;
+ padding: 4px 6px;
+ font-size: 14px;
+ font-weight: 800;
+ color: inherit;
+ text-decoration: none;
+ background-color: var(--bg-highlited);
+ background-image: initial;
+ border-radius: 4px;
+}
+
+@media (prefers-color-scheme: dark) {
+ .Badge__githubLogo {
+ filter: invert(1);
+ }
+}
diff --git a/client/view/Badge/github_logo.svg b/client/view/Badge/github_logo.svg
new file mode 100644
index 00000000..f281286c
--- /dev/null
+++ b/client/view/Badge/github_logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/Badge/twitter_logo.svg b/client/view/Badge/twitter_logo.svg
new file mode 100644
index 00000000..1de65336
--- /dev/null
+++ b/client/view/Badge/twitter_logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/BrowserStats/BrowsersStat.css b/client/view/BrowserStats/BrowsersStat.css
new file mode 100644
index 00000000..42e869cd
--- /dev/null
+++ b/client/view/BrowserStats/BrowsersStat.css
@@ -0,0 +1,183 @@
+.BrowsersStat__regionCoverageBar {
+ display: flex;
+ gap: 1px;
+ justify-content: flex-start;
+ width: 100%;
+ padding: 0;
+ margin: 0 0 24px;
+ overflow: hidden;
+ counter-reset: alpha 0;
+ background-color: var(--main-bg);
+ border-radius: 6px;
+}
+
+.BrowsersStat__regionCoverageBarItem {
+ box-sizing: border-box;
+ width: calc(var(--proportion, 0) * 1%);
+ overflow: hidden;
+ line-height: 32px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ list-style: none;
+ counter-increment: alpha -1;
+ background-color: var(--accent-alternave);
+ opacity: var(--alpha, 0%);
+
+ /* TODO types for this variables */
+ --proportion: 0;
+ --alpha: 0;
+}
+
+.BrowsersStat__regionCoverageBarItem--texted::after,
+.BrowsersStat__regionCoverageBarItem--texted::before {
+ display: inline-block;
+ width: 8px;
+ content: "";
+}
+
+.BrowsersStat__tableContainer {
+ columns: 2;
+ column-fill: balance;
+}
+
+@media (min-width: 740px) and (max-width: 1200px) {
+ .BrowsersStat__tableContainer {
+ columns: 1;
+ }
+}
+
+@media (max-width: 600px) {
+ .BrowsersStat__tableContainer {
+ columns: 1;
+ }
+}
+
+.BrowsersStat__placeholder {
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ gap: 32px;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ color: var(--separator);
+}
+
+@media (max-width: 740px) {
+ .BrowsersStat__placeholder {
+ gap: 16px;
+ padding: 32px 0;
+ }
+}
+
+.BrowsersStat__placeholderImage {
+ width: 100%;
+ object-fit: cover;
+ max-width: 380px;
+}
+
+@media (max-width: 740px) {
+ .BrowsersStat__placeholderImage {
+ width: initial;
+ max-width: 100%;
+ max-height: 300px;
+ }
+}
+
+.BrowsersStat {
+ flex-grow: 1;
+}
+
+.BrowsersStat__placeholderText {
+ width: 80%;
+ margin: 0;
+ text-align: center;
+}
+
+.BrowsersStat__placeholder--hidden {
+ display: none;
+}
+
+.BrowsersStat__stat {
+ display: flex;
+ flex-direction: column;
+ min-height: 100%;
+}
+
+.BrowsersStat__stat--hidden {
+ display: none;
+}
+
+.BrowsersStat__table {
+ display: block;
+ border-spacing: 8px 0;
+}
+
+.BrowsersStat__table tr:first-child td:first-child {
+ width: 20px;
+}
+
+.BrowsersStat__table tr:first-child td:nth-child(2) {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.BrowsersStat__table tr:first-child td:nth-child(3) {
+ width: 7ch;
+}
+
+.BrowsersStat__td {
+ box-sizing: border-box;
+ height: 32px;
+ line-height: 32px;
+ vertical-align: top;
+ break-inside: avoid;
+}
+
+.BrowsersStat__td:last-child {
+ width: 6ch;
+ text-align: left;
+}
+
+.BrowsersStat__td--coverage {
+ --coverage: 20%;
+
+ background-image:
+ linear-gradient(
+ to right,
+ var(--accent-alternave) var(--coverage),
+ transparent var(--coverage),
+ transparent
+ );
+}
+
+.BrowsersStat__table tbody {
+ display: inline-table;
+ width: 100%;
+ margin-bottom: -1px;
+ table-layout: fixed;
+ border-top: 1px solid var(--separator);
+}
+
+.BrowsersStat__icon {
+ display: inline;
+ height: 20px;
+ line-height: 32px;
+ vertical-align: middle;
+}
+
+.BrowsersStat__toolsVersions {
+ display: flex;
+ flex-wrap: wrap;
+ column-gap: 12px;
+ color: var(--text-secondary);
+ margin-top: auto;
+ padding-top: 24px;
+}
+
+.BrowsersStat__toolsVersionsItem {
+ font-size: 14px;
+ line-height: 20px;
+ margin: 0;
+}
diff --git a/client/view/BrowserStats/browserStats.js b/client/view/BrowserStats/browserStats.js
new file mode 100644
index 00000000..f442543b
--- /dev/null
+++ b/client/view/BrowserStats/browserStats.js
@@ -0,0 +1,143 @@
+import wikipediaLinks from '../../data/wikipedia-links.js'
+import * as browsersIcons from '../../data/browsers-logos.js'
+
+export function updateRegionCoverageCounter(coverage) {
+ let element = document.querySelector('[data-id=region_coverage_counter]')
+ element.innerHTML = coverage + '%'
+}
+
+export function updateRegionCoverageBar(data) {
+ let element = document.querySelector('[data-id=region_coverage_bar]')
+ element.innerHTML = ''
+ data.forEach(item => {
+ let itemElem = document.createElement('li')
+ itemElem.classList.add('BrowsersStat__regionCoverageBarItem')
+ itemElem.style.setProperty('--proportion', item.coverage)
+ itemElem.style.setProperty('--alpha', 1 - 1 / item.coverage)
+ if (item.coverage > 10) {
+ itemElem.innerHTML = item.name
+ itemElem.classList.add('BrowsersStat__regionCoverageBarItem--texted')
+ }
+ element.appendChild(itemElem)
+ })
+}
+
+export function showStats() {
+ let statsPlaceholder = document.querySelector(
+ '[data-id=browsers_stats_placeholder]'
+ )
+ let browserStats = document.querySelector('[data-id=browsers_stats]')
+
+ statsPlaceholder.classList.add('BrowsersStat__placeholder--hidden')
+ browserStats.classList.remove('BrowsersStat__stat--hidden')
+}
+
+function createCoverageCell(coverage) {
+ let coveragePercentageHtmlString = cov => cov + '%'
+ let coveragePercentageCssString = cov => {
+ let result = (Math.log(1 + cov) * 100) / Math.log(1 + 100)
+ if (result === 0) {
+ return '0'
+ } else if (result > 5) {
+ return result + '%'
+ }
+ return '1px'
+ }
+
+ let coverageCell = document.createElement('td')
+ coverageCell.classList.add('BrowsersStat__td')
+ coverageCell.innerHTML = coveragePercentageHtmlString(coverage)
+ coverageCell.classList.add('BrowsersStat__td--coverage')
+
+ coverageCell.style.setProperty(
+ '--coverage',
+ coveragePercentageCssString(coverage)
+ )
+ return coverageCell
+}
+
+function createVersionCell(version) {
+ let versionCell = document.createElement('td')
+ versionCell.classList.add('BrowsersStat__td')
+ versionCell.innerHTML = version
+ return versionCell
+}
+
+export function updateBrowsersStats(data) {
+ let element = document.querySelector('[data-id=browsers_stats_results]')
+
+ let table = document.createElement('table')
+ table.classList.add('BrowsersStat__table')
+
+ data.forEach(({ id, name, versions: versionsInput }) => {
+ let versions = Object.entries(versionsInput)
+ .sort(([versionA], [versionB]) => versionB - versionA)
+ .map(([version, coverage]) => {
+ return {
+ version,
+ coverage
+ }
+ })
+
+ let tBody = document.createElement('tbody')
+ let tr = document.createElement('tr')
+ tr.classList.add('BrowsersStat_tr')
+
+ let iconCell = document.createElement('td')
+ iconCell.classList.add('BrowsersStat__td')
+ iconCell.setAttribute('rowspan', versions.length)
+ tr.appendChild(iconCell)
+
+ if (id in browsersIcons) {
+ let iconElem = document.createElement('img')
+ iconElem.classList.add('BrowsersStat__icon')
+ iconElem.src = browsersIcons[id]
+ iconElem.setAttribute('alt', '')
+ iconCell.appendChild(iconElem)
+ }
+
+ let nameCell = document.createElement('td')
+ nameCell.classList.add('BrowsersStat__td')
+ let nameLink = document.createElement('a')
+ nameLink.classList.add('Link')
+ // TODO Need to take care of the case when we do not have link for some browser. Can I Use sometimes adds browsers
+ nameLink.href = wikipediaLinks[id]
+ nameLink.rel = 'noreferrer noopener'
+ nameLink.target = '_blank'
+ nameCell.setAttribute('rowspan', versions.length)
+ nameLink.innerHTML = name
+ nameCell.appendChild(nameLink)
+ tr.appendChild(nameCell)
+
+ tr.appendChild(createVersionCell(versions[0].version))
+
+ tr.appendChild(createCoverageCell(versions[0].coverage))
+
+ tBody.appendChild(tr)
+
+ versions.slice(1).forEach(item => {
+ let { version, coverage } = item
+ let versionTr = document.createElement('tr')
+
+ versionTr.appendChild(createVersionCell(version))
+
+ versionTr.appendChild(createCoverageCell(coverage))
+
+ tBody.appendChild(versionTr)
+ })
+ table.appendChild(tBody)
+ })
+
+ element.innerHTML = ''
+ element.appendChild(table)
+}
+
+export function updateToolsVersions({ browserslist, caniuse }) {
+ let canIUseElement = document.querySelector('[data-id=can_i_use_version]')
+ canIUseElement.innerHTML = caniuse
+
+ let browsersListElement = document.querySelector(
+ '[data-id=browsers_list_version]'
+ )
+ browsersListElement.innerHTML = browserslist
+}
diff --git a/client/view/BrowserStats/hedgehog.svg b/client/view/BrowserStats/hedgehog.svg
new file mode 100644
index 00000000..04c1bcec
--- /dev/null
+++ b/client/view/BrowserStats/hedgehog.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/DocSection/DocSection.css b/client/view/DocSection/DocSection.css
new file mode 100644
index 00000000..b3840e35
--- /dev/null
+++ b/client/view/DocSection/DocSection.css
@@ -0,0 +1,61 @@
+.DocSection {
+ padding: 16px;
+ background-color: var(--bg-highlited);
+ border-radius: 8px;
+}
+
+.DocSection + .DocSection {
+ margin-top: 24px;
+}
+
+.DocSection__header {
+ margin: 0;
+ font-size: 18px;
+ font-weight: 600;
+ line-height: 24px;
+}
+
+.DocSection p {
+ font-size: 16px;
+ line-height: 22px;
+}
+
+.DocSection__subHeader {
+ margin-top: 24px;
+ margin-bottom: 10px;
+ font-size: 12px;
+ font-weight: 800;
+ line-height: 16px;
+ text-transform: uppercase;
+}
+
+summary .DocSection__subHeader {
+ display: inline-block;
+ margin-bottom: 0;
+}
+
+.DocSection details summary {
+ width: fit-content;
+ cursor: pointer;
+}
+
+.DocSection details[open] summary {
+ margin-bottom: 8px;
+}
+
+.DocSection__list {
+ padding: 0;
+ margin: 0;
+}
+
+.DocSection__list li {
+ margin: 0;
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 22px;
+ list-style: none;
+}
+
+.DocSection__list li + li {
+ margin-top: 10px;
+}
diff --git a/client/view/Form/Form.css b/client/view/Form/Form.css
new file mode 100644
index 00000000..bbd0d90d
--- /dev/null
+++ b/client/view/Form/Form.css
@@ -0,0 +1,163 @@
+.Form {
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+}
+
+.Form__queryTextAreaContainer {
+ position: relative;
+}
+
+.Form__queryTextArea {
+ box-sizing: border-box;
+ width: 100%;
+ padding: 12px;
+ font-family: monospace, monospace;
+ font-size: inherit;
+ color: inherit;
+ background-color: var(--main-bg);
+ border: none;
+ border-radius: 8px;
+}
+
+.Form__queryTextArea::placeholder {
+ opacity: 0%;
+}
+
+.Form__queryTextArea:focus-visible {
+ outline-color: var(--accent);
+}
+
+.Form__hint,
+.Form__loader {
+ position: absolute;
+ bottom: 16px;
+ left: 16px;
+ max-width: calc(100% - 12px * 2);
+ margin: 0;
+ font-size: 14px;
+ font-weight: 500;
+ line-height: 1;
+ color: var(--text-secondary);
+ overflow-wrap: break-word;
+ pointer-events: none;
+ background-color: var(--main-bg);
+ opacity: 0%;
+ transition: opacity 0.2s linear;
+}
+
+.Form__hint--hidden {
+ opacity: 0%;
+}
+
+.Form__enterIcon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ margin: calc((20px - 1em) / -2) 0;
+ vertical-align: middle;
+ background-color: var(--bg-highlited);
+ border-radius: 2px;
+}
+
+.Form__interactivePlaceholder {
+ position: absolute;
+ top: 12px;
+ left: 12px;
+ margin: 0;
+ font-family: monospace, monospace;
+ color: var(--text-secondary);
+ pointer-events: none;
+ opacity: 0%;
+}
+
+.Form__hint--required {
+ color: var(--warning);
+}
+
+.Form__hint--error {
+ color: var(--error);
+}
+
+.Form__hint--error a {
+ color: inherit;
+ pointer-events: initial;
+}
+
+.Form.Form--serverError:not(.Form--loaded) .Form__hint--error {
+ opacity: 100%;
+}
+
+.Form__queryTextArea:placeholder-shown ~ .Form__interactivePlaceholder {
+ pointer-events: none;
+ opacity: 100%;
+}
+
+.Form__queryTextArea:placeholder-shown ~ .Form__interactivePlaceholder a {
+ pointer-events: initial;
+}
+
+.Form:not(.Form--serverError):not(.Form--loaded) .Form__queryTextArea:invalid:focus-visible ~ .Form__hint--required {
+ opacity: 100%;
+}
+
+.Form:not(.Form--serverError):not(.Form--justSend):not(.Form--loaded) .Form__queryTextArea:focus-visible:valid ~ .Form__hint--progress {
+ opacity: 100%;
+}
+
+.Form--loaded .Form__loader {
+ opacity: 100%;
+}
+
+.Form__loader::after {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ margin-left: 1ch;
+ content: "";
+ background-image:
+ radial-gradient(var(--main-bg) 60%, transparent 60%),
+ conic-gradient(transparent, currentcolor);
+ border-radius: 50%;
+ animation-name: form-loader;
+ animation-duration: 1s;
+ animation-timing-function: cubic-bezier(0.5, 0.2, 0.5, 0.8);
+ animation-iteration-count: infinite;
+}
+
+@keyframes form-loader {
+ 0% {
+ transform: rotate(0);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.Form__coverage {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.Form__coverage--hidden {
+ display: none;
+}
+
+.Form__coverageSelect {
+ width: fit-content;
+ max-width: 200px;
+ padding: 2px 8px;
+ font-size: 16px;
+ line-height: 20px;
+ color: var(--accent);
+ background-color: var(--main-bg);
+ background-image: none;
+ border: none;
+ border-radius: 4px;
+}
diff --git a/client/view/Form/form.js b/client/view/Form/form.js
new file mode 100644
index 00000000..eec7012a
--- /dev/null
+++ b/client/view/Form/form.js
@@ -0,0 +1,196 @@
+import { DEFAULT_REGION, regionList, regionGroups } from '../../data/regions.js'
+import {
+ updateBrowsersStats,
+ updateRegionCoverageCounter,
+ updateRegionCoverageBar,
+ updateToolsVersions,
+ showStats
+} from '../BrowserStats/browserStats.js'
+
+const form = document.querySelector('[data-id=query_form]')
+const textarea = document.querySelector('[data-id=query_text_area]')
+const regionCoverage = document.querySelector('[data-id=region_coverage]')
+const regionCoverageSelect = document.querySelector(
+ '[data-id=region_coverage_select]'
+)
+const errorMessage = document.querySelector('[data-id=error_message]')
+
+form.addEventListener('submit', handleFormSubmit)
+
+textarea.addEventListener('keypress', e => {
+ if (e.key === 'Enter' && !e.shiftKey) {
+ e.preventDefault()
+ submitForm()
+ }
+})
+
+renderRegionSelectOptions()
+
+regionCoverageSelect.addEventListener('change', () => {
+ submitForm()
+})
+
+submitFormWithUrlParams()
+
+window.addEventListener('popstate', () => {
+ submitFormWithUrlParams()
+})
+
+function handleFormSubmit(e) {
+ e.preventDefault()
+ if (!form.checkValidity()) {
+ return
+ }
+
+ let formData = new FormData(form)
+ let query = formData.get('query')
+ let region = formData.get('region')
+
+ changeUrl(query, region)
+
+ e.preventDefault()
+ form.classList.add('Form--justSend')
+ textarea.addEventListener(
+ 'input',
+ () => {
+ form.classList.remove('Form--justSend')
+ },
+ {
+ once: true
+ }
+ )
+ updateStatsView(query, region)
+}
+
+export function setFormValues({ query, region }) {
+ if (query) {
+ textarea.value = query
+ form.classList.remove('Form--serverError')
+ }
+
+ let isRegionExists = regionList.includes(region)
+
+ if (region && isRegionExists) {
+ regionCoverageSelect.value = region
+ }
+}
+
+export function submitForm() {
+ form.dispatchEvent(new Event('submit', { cancelable: true }))
+}
+
+function showCoverageControls() {
+ regionCoverage.classList.remove('Form__coverage--hidden')
+}
+
+function renderRegionSelectOptions() {
+ let renderOptgroups = ({ continents, countries }) => {
+ let renderOption = (id, name) => {
+ let option = document.createElement('option')
+ option.value = id
+ option.innerHTML = name
+ return option
+ }
+
+ let renderOptgroup = (groupName, regionsGroup) => {
+ let optgroup = document.createElement('optgroup')
+ optgroup.label = groupName
+ for (let { id, name } of regionsGroup) {
+ let option = renderOption(id, name)
+ optgroup.appendChild(option)
+ }
+ return optgroup
+ }
+
+ return {
+ continentsOptgroup: renderOptgroup('Continents', continents),
+ countriesOptgroup: renderOptgroup('Countries', countries)
+ }
+ }
+
+ let { continentsOptgroup, countriesOptgroup } = renderOptgroups(regionGroups)
+ regionCoverageSelect.appendChild(continentsOptgroup)
+ regionCoverageSelect.appendChild(countriesOptgroup)
+}
+
+function renderError(message) {
+ errorMessage.innerHTML = message
+ form.classList.add('Form--serverError')
+ textarea.addEventListener(
+ 'input',
+ () => {
+ form.classList.remove('Form--serverError')
+ },
+ {
+ once: true
+ }
+ )
+}
+
+async function updateStatsView(query, region) {
+ let response
+ try {
+ form.classList.add('Form--loaded')
+ let urlParams = new URLSearchParams({ q: query, region })
+ response = await fetch(`/api/browsers?${urlParams}`)
+ } catch (error) {
+ renderError(`Network error. Check that you are online.`)
+ form.classList.remove('Form--loaded')
+ return false
+ }
+
+ let data = await response.json()
+
+ form.classList.remove('Form--loaded')
+
+ if (!response.ok) {
+ if (data.message === 'Custom usage statistics was not provided') {
+ renderError(`This website does not support in my stats queries yet. Run Browserslist
+ locally .`)
+ return false
+ }
+ if (response.status === 500) {
+ renderError(`Server error.
+Report an issue to our repository.`)
+ return false
+ }
+ renderError(data.message)
+ return false
+ }
+
+ let { browsers, coverage, versions } = data
+
+ showCoverageControls()
+ showStats()
+ updateBrowsersStats(browsers)
+ updateRegionCoverageCounter(coverage)
+ updateRegionCoverageBar(browsers)
+ updateToolsVersions(versions)
+
+ return true
+}
+
+function changeUrl(query, region) {
+ let urlParams = new URLSearchParams()
+ if (query) {
+ urlParams.set('q', query)
+ }
+
+ if (region && region !== DEFAULT_REGION) {
+ urlParams.set('region', region)
+ }
+
+ window.history.pushState({}, query, '?' + urlParams)
+}
+
+function submitFormWithUrlParams() {
+ let urlParams = new URLSearchParams(window.location.search)
+
+ let query = urlParams.get('q')
+ let region = urlParams.get('region')
+
+ if (!query) return
+
+ setFormValues({ query, region })
+ submitForm()
+}
diff --git a/client/view/Link/Link.css b/client/view/Link/Link.css
new file mode 100644
index 00000000..d55dbfc5
--- /dev/null
+++ b/client/view/Link/Link.css
@@ -0,0 +1,17 @@
+.Link {
+ padding-bottom: 0.2em;
+ margin-bottom: -0.2em;
+ color: var(--text-primary);
+ text-decoration-line: underline;
+ text-decoration-style: solid;
+ text-decoration-color: var(--text-secondary);
+ text-underline-offset: 2px;
+ transition: text-decoration-color 0.3s;
+}
+
+@media (hover) {
+ .Link:hover {
+ text-decoration-color: currentcolor;
+ background-position: 0 1.1em;
+ }
+}
diff --git a/client/view/Pre/Pre.css b/client/view/Pre/Pre.css
new file mode 100644
index 00000000..4c186940
--- /dev/null
+++ b/client/view/Pre/Pre.css
@@ -0,0 +1,17 @@
+.Pre {
+ display: flex;
+ flex-direction: column;
+ padding: 12px;
+ font-size: inherit;
+ color: var(--accent);
+ background-color: var(--text-highlited);
+ border-radius: 8px;
+ transition: background-color 0.3s;
+}
+
+.Pre code {
+ overflow: hidden;
+ font-size: inherit;
+ white-space: pre-wrap;
+ background-color: initial;
+}
diff --git a/client/view/QueryLink/QueryLink.css b/client/view/QueryLink/QueryLink.css
new file mode 100644
index 00000000..0583bffb
--- /dev/null
+++ b/client/view/QueryLink/QueryLink.css
@@ -0,0 +1,19 @@
+.QueryLink {
+ cursor: pointer;
+}
+
+@media (hover) {
+ .QueryLink:hover > code,
+ .QueryLink:hover > pre {
+ background-color: var(--text-highlited-hover);
+ }
+}
+
+.QueryLink > code {
+ padding: 0 4px;
+ line-height: 20px;
+ color: var(--accent);
+ background-color: var(--text-highlited);
+ border-radius: 4px;
+ transition: background-color 0.3s;
+}
diff --git a/client/view/QueryLink/queryLink.js b/client/view/QueryLink/queryLink.js
new file mode 100644
index 00000000..bcaf056f
--- /dev/null
+++ b/client/view/QueryLink/queryLink.js
@@ -0,0 +1,21 @@
+import { setFormValues, submitForm } from '../Form/form.js'
+
+const queryContainer = document.querySelector('[data-id=query_container]')
+const links = document.querySelectorAll('a.QueryLink')
+
+links.forEach(item => {
+ item.addEventListener('click', e => {
+ e.preventDefault()
+ let queryAttr = item.getAttribute('data-query')
+ if (queryAttr) {
+ setFormValues({ query: queryAttr })
+ } else {
+ setFormValues({ query: item.innerText.trim() })
+ }
+
+ submitForm()
+
+ queryContainer.scrollTo({ top: 0 })
+ queryContainer.scrollIntoView()
+ })
+})
diff --git a/client/view/Tweet/Tweet.css b/client/view/Tweet/Tweet.css
new file mode 100644
index 00000000..ee8d61b4
--- /dev/null
+++ b/client/view/Tweet/Tweet.css
@@ -0,0 +1,86 @@
+.Tweet {
+ position: relative;
+ z-index: 1;
+ height: fit-content;
+ padding: 16px;
+ overflow: hidden;
+ pointer-events: none;
+ border: 1px solid var(--separator);
+ border-radius: 12px;
+}
+
+.Tweet__link {
+ position: absolute;
+ inset: 0;
+ z-index: -1;
+ pointer-events: all;
+ transition: background-color 0.3s;
+}
+
+@media (hover) {
+ .Tweet__link:hover {
+ background-color: var(--text-highlited);
+ }
+}
+
+.Tweet__address {
+ position: relative;
+ display: grid;
+ grid-template-columns: 40px 1fr;
+ grid-auto-rows: 1fr 1fr;
+ column-gap: 10px;
+ margin-bottom: 10px;
+ font-style: normal;
+}
+
+.Tweet__address::after {
+ position: absolute;
+ bottom: -3px;
+ left: 26px;
+ width: 16px;
+ height: 16px;
+ content: "";
+ background-color: var(--twitter);
+ background-image: url(./twitter_white.svg);
+ background-repeat: no-repeat;
+ background-position: center;
+ border-radius: 50%;
+}
+
+.Tweet__img {
+ grid-row: span 2;
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+}
+
+.Tweet__nickName {
+ color: var(--text-secondary);
+ text-decoration: none;
+}
+
+.Tweet__name {
+ font-weight: 600;
+}
+
+.Tweet__text {
+ margin: 0;
+}
+
+.Tweet__text a {
+ color: var(--accent);
+ text-decoration: none;
+ pointer-events: initial;
+}
+
+@media (hover) {
+ .Tweet__text a:hover {
+ text-decoration: underline;
+ }
+}
+
+.Tweet__list {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 12px;
+}
diff --git a/client/view/Tweet/gha_dev.webp b/client/view/Tweet/gha_dev.webp
new file mode 100644
index 00000000..ca583c66
Binary files /dev/null and b/client/view/Tweet/gha_dev.webp differ
diff --git a/client/view/Tweet/rossta.webp b/client/view/Tweet/rossta.webp
new file mode 100644
index 00000000..7b22b779
Binary files /dev/null and b/client/view/Tweet/rossta.webp differ
diff --git a/client/view/Tweet/twitter_white.svg b/client/view/Tweet/twitter_white.svg
new file mode 100644
index 00000000..8ec83749
--- /dev/null
+++ b/client/view/Tweet/twitter_white.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/base/apple-touch-icon.png b/client/view/base/apple-touch-icon.png
new file mode 100644
index 00000000..0f2c5e28
Binary files /dev/null and b/client/view/base/apple-touch-icon.png differ
diff --git a/client/view/base/colors.css b/client/view/base/colors.css
new file mode 100644
index 00000000..c2c4dae9
--- /dev/null
+++ b/client/view/base/colors.css
@@ -0,0 +1,37 @@
+/* TODO types for this variables */
+
+@media (prefers-color-scheme: light) {
+ :root {
+ --main-bg: oklch(100% 0 0);
+ --bg-highlited: oklch(97% 0.003 286.35);
+ --accent: oklch(53.05% 0.192 258.53);
+ --text-highlited: oklch(53% 0.192 258.53 / 7%);
+ --text-highlited-hover: oklch(57.37% 0.195 257.86 / 14%);
+ --text-primary: oklch(11.264% 0.1 139.088);
+ --text-secondary: oklch(23.5% 0 0 / 40%);
+ --accent-blue-primary: oklch(43.639% 45.224 280.199);
+ --accent-alternave: oklch(88.4% 0.41 92.834);
+ --separator: oklch(23.5% 0 0 / 12%);
+ --warning: oklch(73% 100 65.45 / 80%);
+ --error: oklch(66% 0.096 30.71);
+ --twitter: oklch(70.35% 0.124 234.85);
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --main-bg: oklch(23.5% 0 0);
+ --bg-highlited: oklch(30.72% 0.009 285.86);
+ --accent: oklch(77.05% 0.12 255);
+ --text-highlited: oklch(66.37% 0.18 256.56 / 20%);
+ --text-highlited-hover: oklch(66.37% 0.185 256.56 / 30%);
+ --text-primary: oklch(100% 0.1 139.088);
+ --text-secondary: oklch(60% 0.01 257);
+ --accent-blue-primary: oklch(43.639% 45.224 280.199);
+ --accent-alternave: oklch(63.02% 0.13 78.82);
+ --separator: oklch(100% 3.55 106.37 / 12%);
+ --warning: oklch(47.96% 0.103 65.45);
+ --error: oklch(66% 0.096 30.71);
+ --twitter: oklch(70.35% 0.124 234.85);
+ }
+}
diff --git a/client/view/base/icon.svg b/client/view/base/icon.svg
new file mode 100644
index 00000000..ef709633
--- /dev/null
+++ b/client/view/base/icon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/view/base/index.css b/client/view/base/index.css
new file mode 100644
index 00000000..61f8ce9a
--- /dev/null
+++ b/client/view/base/index.css
@@ -0,0 +1,48 @@
+@import "../BrowserStats/BrowsersStat.css";
+@import "../Article/Article.css";
+@import "../Form/Form.css";
+@import "../Badge/Badge.css";
+@import "../QueryLink/QueryLink.css";
+@import "../DocSection/DocSection.css";
+@import "../Link/Link.css";
+@import "../Pre/Pre.css";
+@import "../Tweet/Tweet.css";
+
+@media (prefers-reduced-motion: reduce) {
+ * {
+ transition: none !important;
+ }
+}
+
+body {
+ margin: 0;
+ font-family:
+ -apple-system,
+ BlinkMacSystemFont,
+ "Segoe UI",
+ Roboto,
+ Oxygen,
+ Ubuntu,
+ Cantarell,
+ "Fira Sans",
+ "Droid Sans",
+ "Helvetica Neue",
+ sans-serif;
+ color: var(--text-primary);
+ overflow-wrap: break-word;
+ background-color: var(--main-bg);
+ accent-color: var(--accent);
+}
+
+p {
+ font-size: 16px;
+ line-height: 22px;
+ letter-spacing: 0.01em;
+}
+
+code {
+ /* stylelint-disable-next-line font-family-no-duplicate-names */
+ font-family: monospace, monospace;
+
+ /* explain: https://github.com/necolas/normalize.css/issues/519#issuecomment-197131966 */
+}
diff --git a/client/vite.config.js b/client/vite.config.js
new file mode 100644
index 00000000..f128a1f2
--- /dev/null
+++ b/client/vite.config.js
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vite'
+import vitePluginPug from 'vite-plugin-pug-transformer'
+
+export default defineConfig({
+ build: {
+ assetsDir: '.',
+ assetsInlineLimit: 0
+ },
+ plugins: [vitePluginPug()]
+})
diff --git a/index.html b/index.html
deleted file mode 100644
index 4eeb989c..00000000
--- a/index.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
- Help Browserslist
-
-
-
-
- Browserslist website is down.Help us make a new and better website.
- Short-term solution
- Use CLI tool instead of the websitenpx browserslist "last 1 version, >1%"
- Long-term solution
-
- Why Browserslist is important for JS ecosystem?
- Browserslist is used by many popular tools, including Autoprefixer, Babel, Gatsby, Next.js, Create React App, and other 600+ projects . It has 75+ million downloads per month .
- It helps to keep browsers diversity by moving the focus from few well-know Western browsers (like chrome: 60
) to general queries (like 1 last version, >1%
or supports es6-module and >0.5% in my stats
).
- You can learn more about philosophy under Browserslist in our interview with Google’s The State of the Web.
-
-
- xkcd: Dependency
-
- How will we use your donations?
-
- We will pay to the designer and make a redesign for the website.
- We will refactor the website to run it in a new hosting.
- In the new website design, we will Browserslist config best practices to promote browser diversity.
- We will refactor the Browserslist data updates system to avoid the security issue similar to the recent ESLint issue .
- Add Browserslist config linter.
-
-
-
-
\ No newline at end of file
diff --git a/nano-staged.json b/nano-staged.json
new file mode 100644
index 00000000..fb6147b0
--- /dev/null
+++ b/nano-staged.json
@@ -0,0 +1,5 @@
+{
+ "*.css": "stylelint --fix",
+ "*.js": "prettier --write",
+ "*.svg": "svgo"
+}
diff --git a/package.json b/package.json
index 9443f60f..266d8569 100644
--- a/package.json
+++ b/package.json
@@ -1,26 +1,42 @@
{
- "name": "browserlist",
- "version": "0.0.0",
+ "name": "browserl.ist",
"private": true,
+ "homepage": "https://browsersl.ist/",
+ "type": "module",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
"scripts": {
- "build": "",
- "lint": "eslint bin/www .",
- "deploy": "script/deploy",
- "start": "node ./bin/www",
- "test": "npm run lint"
+ "start": "pnpm -r start",
+ "build": "pnpm -r build",
+ "lint": "eslint . && stylelint **/*.css",
+ "test": "pnpm audit --prod && pnpm lint && pnpm -r test"
},
"dependencies": {
- "body-parser": "^1.19.0",
- "browserslist": "4.8.3",
- "caniuse-db": "1.0.30001019",
- "cookie-parser": "^1.4.4",
- "debug": "^4.1.1",
- "express": "^4.17.1",
- "morgan": "^1.9.1",
- "pug": "^2.0.4"
+ "ssdeploy": "^0.9.1"
},
"devDependencies": {
- "eslint": "^6.6.0",
- "eslint-plugin-github": "^3.2.1"
+ "@logux/eslint-config": "^47.2.0",
+ "@logux/stylelint-config": "^0.10.1",
+ "@typescript-eslint/eslint-plugin": "^5.33.0",
+ "@typescript-eslint/parser": "^5.33.0",
+ "eslint": "^8.21.0",
+ "eslint-config-standard": "^17.0.0",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-n": "^15.2.4",
+ "eslint-plugin-prefer-let": "^3.0.1",
+ "eslint-plugin-promise": "^6.0.0",
+ "nano-staged": "^0.8.0",
+ "prettier": "^2.7.1",
+ "simple-git-hooks": "^2.8.0",
+ "stylelint": "^14.10.0",
+ "svgo": "^2.8.0",
+ "typescript": "^4.7.4"
+ },
+ "pnpm": {
+ "overrides": {
+ "markdown-it@<12.3.2": ">=12.3.2"
+ }
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 00000000..0c7d81ab
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,3208 @@
+lockfileVersion: 5.4
+
+overrides:
+ markdown-it@<12.3.2: '>=12.3.2'
+
+importers:
+
+ .:
+ specifiers:
+ '@logux/eslint-config': ^47.2.0
+ '@logux/stylelint-config': ^0.10.1
+ '@typescript-eslint/eslint-plugin': ^5.33.0
+ '@typescript-eslint/parser': ^5.33.0
+ eslint: ^8.21.0
+ eslint-config-standard: ^17.0.0
+ eslint-plugin-import: ^2.26.0
+ eslint-plugin-n: ^15.2.4
+ eslint-plugin-prefer-let: ^3.0.1
+ eslint-plugin-promise: ^6.0.0
+ nano-staged: ^0.8.0
+ prettier: ^2.7.1
+ simple-git-hooks: ^2.8.0
+ ssdeploy: ^0.9.1
+ stylelint: ^14.10.0
+ svgo: ^2.8.0
+ typescript: ^4.7.4
+ dependencies:
+ ssdeploy: 0.9.1
+ devDependencies:
+ '@logux/eslint-config': 47.2.0_7hz3xvmviof7onfgk6hpedqcom
+ '@logux/stylelint-config': 0.10.1_stylelint@14.10.0
+ '@typescript-eslint/eslint-plugin': 5.33.0_njno5y7ry2l2lcmiu4tywxkwnq
+ '@typescript-eslint/parser': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq
+ eslint: 8.21.0
+ eslint-config-standard: 17.0.0_dfwa53o44x4e5xhsfv5mvfhk5a
+ eslint-plugin-import: 2.26.0_qfqnhzzittf54udqwes54xx65q
+ eslint-plugin-n: 15.2.4_eslint@8.21.0
+ eslint-plugin-prefer-let: 3.0.1
+ eslint-plugin-promise: 6.0.0_eslint@8.21.0
+ nano-staged: 0.8.0
+ prettier: 2.7.1
+ simple-git-hooks: 2.8.0
+ stylelint: 14.10.0
+ svgo: 2.8.0
+ typescript: 4.7.4
+
+ client:
+ specifiers:
+ '@csstools/postcss-oklab-function': ^1.1.1
+ '@size-limit/file': ^8.0.1
+ autoprefixer: ^10.4.8
+ caniuse-lite: ^1.0.30001375
+ jstransformer-markdown-it: ^3.0.0
+ postcss: ^8.4.16
+ postcss-media-minmax: ^5.0.0
+ postcss-nesting: ^10.1.10
+ postcss-opacity-percentage: ^1.1.2
+ size-limit: ^8.0.1
+ vite: ^3.0.7
+ vite-plugin-pug-transformer: ^1.0.2
+ dependencies:
+ '@csstools/postcss-oklab-function': 1.1.1_postcss@8.4.16
+ autoprefixer: 10.4.8_postcss@8.4.16
+ caniuse-lite: 1.0.30001375
+ jstransformer-markdown-it: 3.0.0
+ postcss: 8.4.16
+ postcss-media-minmax: 5.0.0_postcss@8.4.16
+ postcss-nesting: 10.1.10_postcss@8.4.16
+ postcss-opacity-percentage: 1.1.2
+ vite: 3.0.7
+ vite-plugin-pug-transformer: 1.0.2_vite@3.0.7
+ devDependencies:
+ '@size-limit/file': 8.0.1_size-limit@8.0.1
+ size-limit: 8.0.1
+
+ server:
+ specifiers:
+ browserslist: ^4.21.3
+ caniuse-lite: ^1.0.30001375
+ dependencies:
+ browserslist: 4.21.3
+ caniuse-lite: 1.0.30001375
+
+packages:
+
+ /@babel/code-frame/7.18.6:
+ resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/highlight': 7.18.6
+ dev: true
+
+ /@babel/helper-string-parser/7.18.10:
+ resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==}
+ engines: {node: '>=6.9.0'}
+ dev: false
+
+ /@babel/helper-validator-identifier/7.18.6:
+ resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==}
+ engines: {node: '>=6.9.0'}
+
+ /@babel/highlight/7.18.6:
+ resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-validator-identifier': 7.18.6
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ dev: true
+
+ /@babel/parser/7.18.11:
+ resolution: {integrity: sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.18.10
+ dev: false
+
+ /@babel/types/7.18.10:
+ resolution: {integrity: sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.18.10
+ '@babel/helper-validator-identifier': 7.18.6
+ to-fast-properties: 2.0.0
+ dev: false
+
+ /@csstools/postcss-oklab-function/1.1.1_postcss@8.4.16:
+ resolution: {integrity: sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==}
+ engines: {node: ^12 || ^14 || >=16}
+ peerDependencies:
+ postcss: ^8.2
+ dependencies:
+ '@csstools/postcss-progressive-custom-properties': 1.3.0_postcss@8.4.16
+ postcss: 8.4.16
+ postcss-value-parser: 4.2.0
+ dev: false
+
+ /@csstools/postcss-progressive-custom-properties/1.3.0_postcss@8.4.16:
+ resolution: {integrity: sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==}
+ engines: {node: ^12 || ^14 || >=16}
+ peerDependencies:
+ postcss: ^8.3
+ dependencies:
+ postcss: 8.4.16
+ postcss-value-parser: 4.2.0
+ dev: false
+
+ /@csstools/selector-specificity/2.0.2_pnx64jze6bptzcedy5bidi3zdi:
+ resolution: {integrity: sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==}
+ engines: {node: ^12 || ^14 || >=16}
+ peerDependencies:
+ postcss: ^8.2
+ postcss-selector-parser: ^6.0.10
+ dependencies:
+ postcss: 8.4.16
+ postcss-selector-parser: 6.0.10
+
+ /@esbuild/linux-loong64/0.14.54:
+ resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@eslint/eslintrc/1.3.0:
+ resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.4
+ espree: 9.3.3
+ globals: 13.17.0
+ ignore: 5.2.0
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/config-array/0.10.4:
+ resolution: {integrity: sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==}
+ engines: {node: '>=10.10.0'}
+ dependencies:
+ '@humanwhocodes/object-schema': 1.2.1
+ debug: 4.3.4
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/gitignore-to-minimatch/1.0.2:
+ resolution: {integrity: sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==}
+ dev: true
+
+ /@humanwhocodes/object-schema/1.2.1:
+ resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
+ dev: true
+
+ /@logux/eslint-config/47.2.0_7hz3xvmviof7onfgk6hpedqcom:
+ resolution: {integrity: sha512-nNPPkw+kfA2bLyhkxaqGzd3MWSN4S2dUf69xo2syskBd5ZfFk2WT9ssO+yDDUd26yNgN3AmweKztEwyUim9wOQ==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ eslint: ^8.14.0
+ eslint-config-standard: ^17.0.0
+ eslint-plugin-import: ^2.26.0
+ eslint-plugin-n: ^15.1.0
+ eslint-plugin-prefer-let: ^3.0.1
+ eslint-plugin-promise: ^6.0.0
+ dependencies:
+ eslint: 8.21.0
+ eslint-config-standard: 17.0.0_dfwa53o44x4e5xhsfv5mvfhk5a
+ eslint-plugin-import: 2.26.0_qfqnhzzittf54udqwes54xx65q
+ eslint-plugin-n: 15.2.4_eslint@8.21.0
+ eslint-plugin-prefer-let: 3.0.1
+ eslint-plugin-promise: 6.0.0_eslint@8.21.0
+ dev: true
+
+ /@logux/stylelint-config/0.10.1_stylelint@14.10.0:
+ resolution: {integrity: sha512-LdqGWEO/IisgQMhtu2t18ygmFP1c38CD4d2HmFIonTvNPKJAAyGcYexOdi8MkUxdGC3oXR4dwJII3z4apiEhNQ==}
+ peerDependencies:
+ stylelint: ^14.2.0
+ dependencies:
+ stylelint: 14.10.0
+ stylelint-config-recess-order: 3.0.0_stylelint@14.10.0
+ stylelint-config-standard: 25.0.0_stylelint@14.10.0
+ stylelint-order: 5.0.0_stylelint@14.10.0
+ dev: true
+
+ /@nodelib/fs.scandir/2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat/2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk/1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.13.0
+ dev: true
+
+ /@size-limit/file/8.0.1_size-limit@8.0.1:
+ resolution: {integrity: sha512-kwgc5UJQIz5qbRow3atSiW2K7vEIIw4DelT4WLn09cOwcJgWs82Imgz2UqVivHJmCisn/ltPjT4qmxaDfjFflw==}
+ engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ size-limit: 8.0.1
+ dependencies:
+ semver: 7.3.7
+ size-limit: 8.0.1
+ dev: true
+
+ /@trysound/sax/0.2.0:
+ resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
+ engines: {node: '>=10.13.0'}
+ dev: true
+
+ /@types/json-schema/7.0.11:
+ resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
+ dev: true
+
+ /@types/json5/0.0.29:
+ resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ dev: true
+
+ /@types/minimist/1.2.2:
+ resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
+ dev: true
+
+ /@types/normalize-package-data/2.4.1:
+ resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
+ dev: true
+
+ /@types/parse-json/4.0.0:
+ resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==}
+ dev: true
+
+ /@typescript-eslint/eslint-plugin/5.33.0_njno5y7ry2l2lcmiu4tywxkwnq:
+ resolution: {integrity: sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^5.0.0
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq
+ '@typescript-eslint/scope-manager': 5.33.0
+ '@typescript-eslint/type-utils': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq
+ '@typescript-eslint/utils': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq
+ debug: 4.3.4
+ eslint: 8.21.0
+ functional-red-black-tree: 1.0.1
+ ignore: 5.2.0
+ regexpp: 3.2.0
+ semver: 7.3.7
+ tsutils: 3.21.0_typescript@4.7.4
+ typescript: 4.7.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/parser/5.33.0_qugx7qdu5zevzvxaiqyxfiwquq:
+ resolution: {integrity: sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/scope-manager': 5.33.0
+ '@typescript-eslint/types': 5.33.0
+ '@typescript-eslint/typescript-estree': 5.33.0_typescript@4.7.4
+ debug: 4.3.4
+ eslint: 8.21.0
+ typescript: 4.7.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/scope-manager/5.33.0:
+ resolution: {integrity: sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.33.0
+ '@typescript-eslint/visitor-keys': 5.33.0
+ dev: true
+
+ /@typescript-eslint/type-utils/5.33.0_qugx7qdu5zevzvxaiqyxfiwquq:
+ resolution: {integrity: sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '*'
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/utils': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq
+ debug: 4.3.4
+ eslint: 8.21.0
+ tsutils: 3.21.0_typescript@4.7.4
+ typescript: 4.7.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/types/5.33.0:
+ resolution: {integrity: sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@typescript-eslint/typescript-estree/5.33.0_typescript@4.7.4:
+ resolution: {integrity: sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/types': 5.33.0
+ '@typescript-eslint/visitor-keys': 5.33.0
+ debug: 4.3.4
+ globby: 11.1.0
+ is-glob: 4.0.3
+ semver: 7.3.7
+ tsutils: 3.21.0_typescript@4.7.4
+ typescript: 4.7.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/utils/5.33.0_qugx7qdu5zevzvxaiqyxfiwquq:
+ resolution: {integrity: sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ '@types/json-schema': 7.0.11
+ '@typescript-eslint/scope-manager': 5.33.0
+ '@typescript-eslint/types': 5.33.0
+ '@typescript-eslint/typescript-estree': 5.33.0_typescript@4.7.4
+ eslint: 8.21.0
+ eslint-scope: 5.1.1
+ eslint-utils: 3.0.0_eslint@8.21.0
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+ dev: true
+
+ /@typescript-eslint/visitor-keys/5.33.0:
+ resolution: {integrity: sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.33.0
+ eslint-visitor-keys: 3.3.0
+ dev: true
+
+ /acorn-jsx/5.3.2_acorn@8.8.0:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ acorn: 8.8.0
+ dev: true
+
+ /acorn/7.4.1:
+ resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: false
+
+ /acorn/8.8.0:
+ resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /ajv/6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ajv/8.11.0:
+ resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex/5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-styles/3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+ dependencies:
+ color-convert: 1.9.3
+ dev: true
+
+ /ansi-styles/4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /anymatch/3.1.2:
+ resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /argparse/2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ /array-includes/3.1.5:
+ resolution: {integrity: sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ es-abstract: 1.20.1
+ get-intrinsic: 1.1.2
+ is-string: 1.0.7
+ dev: true
+
+ /array-union/2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /array.prototype.flat/1.3.0:
+ resolution: {integrity: sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ es-abstract: 1.20.1
+ es-shim-unscopables: 1.0.0
+ dev: true
+
+ /arrify/1.0.1:
+ resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /asap/2.0.6:
+ resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
+ dev: false
+
+ /assert-never/1.2.1:
+ resolution: {integrity: sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==}
+ dev: false
+
+ /astral-regex/2.0.0:
+ resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /autoprefixer/10.4.8_postcss@8.4.16:
+ resolution: {integrity: sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ browserslist: 4.21.3
+ caniuse-lite: 1.0.30001375
+ fraction.js: 4.2.0
+ normalize-range: 0.1.2
+ picocolors: 1.0.0
+ postcss: 8.4.16
+ postcss-value-parser: 4.2.0
+ dev: false
+
+ /babel-walk/3.0.0-canary-5:
+ resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==}
+ engines: {node: '>= 10.0.0'}
+ dependencies:
+ '@babel/types': 7.18.10
+ dev: false
+
+ /balanced-match/1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ /balanced-match/2.0.0:
+ resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==}
+ dev: true
+
+ /binary-extensions/2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /boolbase/1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+ dev: true
+
+ /brace-expansion/1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion/2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+ dev: false
+
+ /braces/3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
+ /browserslist/4.21.3:
+ resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001375
+ electron-to-chromium: 1.4.217
+ node-releases: 2.0.6
+ update-browserslist-db: 1.0.5_browserslist@4.21.3
+ dev: false
+
+ /builtins/5.0.1:
+ resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
+ dependencies:
+ semver: 7.3.7
+ dev: true
+
+ /bytes-iec/3.1.1:
+ resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==}
+ engines: {node: '>= 0.8'}
+ dev: true
+
+ /bytes/3.1.2:
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+ engines: {node: '>= 0.8'}
+ dev: false
+
+ /call-bind/1.0.2:
+ resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
+ dependencies:
+ function-bind: 1.1.1
+ get-intrinsic: 1.1.2
+
+ /callsites/3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /camelcase-keys/6.2.2:
+ resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==}
+ engines: {node: '>=8'}
+ dependencies:
+ camelcase: 5.3.1
+ map-obj: 4.3.0
+ quick-lru: 4.0.1
+ dev: true
+
+ /camelcase/5.3.1:
+ resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /caniuse-lite/1.0.30001375:
+ resolution: {integrity: sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw==}
+ dev: false
+
+ /chalk/2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+ dev: true
+
+ /chalk/4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /character-parser/2.2.0:
+ resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==}
+ dependencies:
+ is-regex: 1.1.4
+ dev: false
+
+ /chokidar/3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.2
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /ci-job-number/1.2.2:
+ resolution: {integrity: sha512-CLOGsVDrVamzv8sXJGaILUVI6dsuAkouJP/n6t+OxLPeeA4DDby7zn9SB6EUpa1H7oIKoE+rMmkW80zYsFfUjA==}
+ dev: true
+
+ /color-convert/1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+ dependencies:
+ color-name: 1.1.3
+ dev: true
+
+ /color-convert/2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name/1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+ dev: true
+
+ /color-name/1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /colord/2.9.3:
+ resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
+ dev: true
+
+ /commander/7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+ dev: true
+
+ /concat-map/0.0.1:
+ resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
+ dev: true
+
+ /constantinople/4.0.1:
+ resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==}
+ dependencies:
+ '@babel/parser': 7.18.11
+ '@babel/types': 7.18.10
+ dev: false
+
+ /cosmiconfig/7.0.1:
+ resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ '@types/parse-json': 4.0.0
+ import-fresh: 3.3.0
+ parse-json: 5.2.0
+ path-type: 4.0.0
+ yaml: 1.10.2
+ dev: true
+
+ /cross-spawn/7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /css-functions-list/3.1.0:
+ resolution: {integrity: sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /css-select/4.3.0:
+ resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 6.1.0
+ domhandler: 4.3.1
+ domutils: 2.8.0
+ nth-check: 2.1.1
+ dev: true
+
+ /css-tree/1.1.3:
+ resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==}
+ engines: {node: '>=8.0.0'}
+ dependencies:
+ mdn-data: 2.0.14
+ source-map: 0.6.1
+ dev: true
+
+ /css-what/6.1.0:
+ resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /cssesc/3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ /csso/4.2.0:
+ resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==}
+ engines: {node: '>=8.0.0'}
+ dependencies:
+ css-tree: 1.1.3
+ dev: true
+
+ /debug/2.6.9:
+ resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.0.0
+ dev: true
+
+ /debug/3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ dev: true
+
+ /debug/4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+
+ /decamelize-keys/1.1.0:
+ resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ decamelize: 1.2.0
+ map-obj: 1.0.1
+ dev: true
+
+ /decamelize/1.2.0:
+ resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /deep-is/0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ dev: true
+
+ /define-lazy-prop/2.0.0:
+ resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
+ engines: {node: '>=8'}
+ dev: false
+
+ /define-properties/1.1.4:
+ resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-property-descriptors: 1.0.0
+ object-keys: 1.1.1
+ dev: true
+
+ /dir-glob/3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-type: 4.0.0
+ dev: true
+
+ /doctrine/2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /doctrine/3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /doctypes/1.1.0:
+ resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==}
+ dev: false
+
+ /dom-serializer/1.4.1:
+ resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 4.3.1
+ entities: 2.2.0
+ dev: true
+
+ /domelementtype/2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+ dev: true
+
+ /domhandler/4.3.1:
+ resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
+ engines: {node: '>= 4'}
+ dependencies:
+ domelementtype: 2.3.0
+ dev: true
+
+ /domutils/2.8.0:
+ resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
+ dependencies:
+ dom-serializer: 1.4.1
+ domelementtype: 2.3.0
+ domhandler: 4.3.1
+ dev: true
+
+ /dotenv/16.0.1:
+ resolution: {integrity: sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==}
+ engines: {node: '>=12'}
+ dev: false
+
+ /electron-to-chromium/1.4.217:
+ resolution: {integrity: sha512-iX8GbAMij7cOtJPZo02CClpaPMWjvN5meqXiJXkBgwvraNWTNH0Z7F9tkznI34JRPtWASoPM/xWamq3oNb49GA==}
+ dev: false
+
+ /emoji-regex/8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /entities/2.2.0:
+ resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
+ dev: true
+
+ /entities/3.0.1:
+ resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==}
+ engines: {node: '>=0.12'}
+ dev: false
+
+ /error-ex/1.3.2:
+ resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
+ dependencies:
+ is-arrayish: 0.2.1
+ dev: true
+
+ /es-abstract/1.20.1:
+ resolution: {integrity: sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ es-to-primitive: 1.2.1
+ function-bind: 1.1.1
+ function.prototype.name: 1.1.5
+ get-intrinsic: 1.1.2
+ get-symbol-description: 1.0.0
+ has: 1.0.3
+ has-property-descriptors: 1.0.0
+ has-symbols: 1.0.3
+ internal-slot: 1.0.3
+ is-callable: 1.2.4
+ is-negative-zero: 2.0.2
+ is-regex: 1.1.4
+ is-shared-array-buffer: 1.0.2
+ is-string: 1.0.7
+ is-weakref: 1.0.2
+ object-inspect: 1.12.2
+ object-keys: 1.1.1
+ object.assign: 4.1.3
+ regexp.prototype.flags: 1.4.3
+ string.prototype.trimend: 1.0.5
+ string.prototype.trimstart: 1.0.5
+ unbox-primitive: 1.0.2
+ dev: true
+
+ /es-shim-unscopables/1.0.0:
+ resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==}
+ dependencies:
+ has: 1.0.3
+ dev: true
+
+ /es-to-primitive/1.2.1:
+ resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.4
+ is-date-object: 1.0.5
+ is-symbol: 1.0.4
+ dev: true
+
+ /esbuild-android-64/0.14.54:
+ resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-android-arm64/0.14.54:
+ resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-darwin-64/0.14.54:
+ resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-darwin-arm64/0.14.54:
+ resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-freebsd-64/0.14.54:
+ resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-freebsd-arm64/0.14.54:
+ resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-32/0.14.54:
+ resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-64/0.14.54:
+ resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-arm/0.14.54:
+ resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-arm64/0.14.54:
+ resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-mips64le/0.14.54:
+ resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-ppc64le/0.14.54:
+ resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-riscv64/0.14.54:
+ resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-linux-s390x/0.14.54:
+ resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-netbsd-64/0.14.54:
+ resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-openbsd-64/0.14.54:
+ resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-sunos-64/0.14.54:
+ resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-windows-32/0.14.54:
+ resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-windows-64/0.14.54:
+ resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild-windows-arm64/0.14.54:
+ resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /esbuild/0.14.54:
+ resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/linux-loong64': 0.14.54
+ esbuild-android-64: 0.14.54
+ esbuild-android-arm64: 0.14.54
+ esbuild-darwin-64: 0.14.54
+ esbuild-darwin-arm64: 0.14.54
+ esbuild-freebsd-64: 0.14.54
+ esbuild-freebsd-arm64: 0.14.54
+ esbuild-linux-32: 0.14.54
+ esbuild-linux-64: 0.14.54
+ esbuild-linux-arm: 0.14.54
+ esbuild-linux-arm64: 0.14.54
+ esbuild-linux-mips64le: 0.14.54
+ esbuild-linux-ppc64le: 0.14.54
+ esbuild-linux-riscv64: 0.14.54
+ esbuild-linux-s390x: 0.14.54
+ esbuild-netbsd-64: 0.14.54
+ esbuild-openbsd-64: 0.14.54
+ esbuild-sunos-64: 0.14.54
+ esbuild-windows-32: 0.14.54
+ esbuild-windows-64: 0.14.54
+ esbuild-windows-arm64: 0.14.54
+ dev: false
+
+ /escalade/3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /escape-string-regexp/1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+ dev: true
+
+ /escape-string-regexp/4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /eslint-config-standard/17.0.0_dfwa53o44x4e5xhsfv5mvfhk5a:
+ resolution: {integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==}
+ peerDependencies:
+ eslint: ^8.0.1
+ eslint-plugin-import: ^2.25.2
+ eslint-plugin-n: ^15.0.0
+ eslint-plugin-promise: ^6.0.0
+ dependencies:
+ eslint: 8.21.0
+ eslint-plugin-import: 2.26.0_qfqnhzzittf54udqwes54xx65q
+ eslint-plugin-n: 15.2.4_eslint@8.21.0
+ eslint-plugin-promise: 6.0.0_eslint@8.21.0
+ dev: true
+
+ /eslint-import-resolver-node/0.3.6:
+ resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==}
+ dependencies:
+ debug: 3.2.7
+ resolve: 1.22.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-module-utils/2.7.4_xtzkthmenmjo2h753u2dv735yy:
+ resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq
+ debug: 3.2.7
+ eslint: 8.21.0
+ eslint-import-resolver-node: 0.3.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-plugin-es/4.1.0_eslint@8.21.0:
+ resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==}
+ engines: {node: '>=8.10.0'}
+ peerDependencies:
+ eslint: '>=4.19.1'
+ dependencies:
+ eslint: 8.21.0
+ eslint-utils: 2.1.0
+ regexpp: 3.2.0
+ dev: true
+
+ /eslint-plugin-import/2.26.0_qfqnhzzittf54udqwes54xx65q:
+ resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq
+ array-includes: 3.1.5
+ array.prototype.flat: 1.3.0
+ debug: 2.6.9
+ doctrine: 2.1.0
+ eslint: 8.21.0
+ eslint-import-resolver-node: 0.3.6
+ eslint-module-utils: 2.7.4_xtzkthmenmjo2h753u2dv735yy
+ has: 1.0.3
+ is-core-module: 2.10.0
+ is-glob: 4.0.3
+ minimatch: 3.1.2
+ object.values: 1.1.5
+ resolve: 1.22.1
+ tsconfig-paths: 3.14.1
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
+ /eslint-plugin-n/15.2.4_eslint@8.21.0:
+ resolution: {integrity: sha512-tjnVMv2fiXYMnuiIFI8QMtyUFI42SckEEWvi8h68SWGWshfqO6SSCASy24dGMGAiy7NUk6DZt90DM0iNUsmQ5w==}
+ engines: {node: '>=12.22.0'}
+ peerDependencies:
+ eslint: '>=7.0.0'
+ dependencies:
+ builtins: 5.0.1
+ eslint: 8.21.0
+ eslint-plugin-es: 4.1.0_eslint@8.21.0
+ eslint-utils: 3.0.0_eslint@8.21.0
+ ignore: 5.2.0
+ is-core-module: 2.10.0
+ minimatch: 3.1.2
+ resolve: 1.22.1
+ semver: 7.3.7
+ dev: true
+
+ /eslint-plugin-prefer-let/3.0.1:
+ resolution: {integrity: sha512-vbznkkBSXB63d4o1o0NIm5C2ey3V5wKr/25dAvPdydQXdowAcnr69cbLgxd2YAG81IV5eddCO55Lp6gL7wSE4w==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ requireindex: 1.2.0
+ dev: true
+
+ /eslint-plugin-promise/6.0.0_eslint@8.21.0:
+ resolution: {integrity: sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ dependencies:
+ eslint: 8.21.0
+ dev: true
+
+ /eslint-scope/5.1.1:
+ resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
+ engines: {node: '>=8.0.0'}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 4.3.0
+ dev: true
+
+ /eslint-scope/7.1.1:
+ resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+ dev: true
+
+ /eslint-utils/2.1.0:
+ resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==}
+ engines: {node: '>=6'}
+ dependencies:
+ eslint-visitor-keys: 1.3.0
+ dev: true
+
+ /eslint-utils/3.0.0_eslint@8.21.0:
+ resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
+ engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
+ peerDependencies:
+ eslint: '>=5'
+ dependencies:
+ eslint: 8.21.0
+ eslint-visitor-keys: 2.1.0
+ dev: true
+
+ /eslint-visitor-keys/1.3.0:
+ resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /eslint-visitor-keys/2.1.0:
+ resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /eslint-visitor-keys/3.3.0:
+ resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /eslint/8.21.0:
+ resolution: {integrity: sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@eslint/eslintrc': 1.3.0
+ '@humanwhocodes/config-array': 0.10.4
+ '@humanwhocodes/gitignore-to-minimatch': 1.0.2
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.1.1
+ eslint-utils: 3.0.0_eslint@8.21.0
+ eslint-visitor-keys: 3.3.0
+ espree: 9.3.3
+ esquery: 1.4.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ functional-red-black-tree: 1.0.1
+ glob-parent: 6.0.2
+ globals: 13.17.0
+ globby: 11.1.0
+ grapheme-splitter: 1.0.4
+ ignore: 5.2.0
+ import-fresh: 3.3.0
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.1
+ regexpp: 3.2.0
+ strip-ansi: 6.0.1
+ strip-json-comments: 3.1.1
+ text-table: 0.2.0
+ v8-compile-cache: 2.3.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /espree/9.3.3:
+ resolution: {integrity: sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ acorn: 8.8.0
+ acorn-jsx: 5.3.2_acorn@8.8.0
+ eslint-visitor-keys: 3.3.0
+ dev: true
+
+ /esquery/1.4.0:
+ resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /esrecurse/4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /estraverse/4.3.0:
+ resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /estraverse/5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /esutils/2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /fast-deep-equal/3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob/3.2.11:
+ resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
+ /fast-json-stable-stringify/2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fast-levenshtein/2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ dev: true
+
+ /fastest-levenshtein/1.0.16:
+ resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==}
+ engines: {node: '>= 4.9.1'}
+ dev: true
+
+ /fastq/1.13.0:
+ resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /file-entry-cache/6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flat-cache: 3.0.4
+ dev: true
+
+ /fill-range/7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /find-up/4.1.0:
+ resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+ engines: {node: '>=8'}
+ dependencies:
+ locate-path: 5.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /find-up/5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /flat-cache/3.0.4:
+ resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flatted: 3.2.6
+ rimraf: 3.0.2
+ dev: true
+
+ /flatted/3.2.6:
+ resolution: {integrity: sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==}
+ dev: true
+
+ /folder-hash/4.0.2:
+ resolution: {integrity: sha512-Iw9GCqdA+zHfDVvk90TSAV66jq0IwiZaPvPgUiW+DHRwnaPOeZomzlgutx9QclinsQGz/XcVIGlDEJbFhCV5wA==}
+ engines: {node: '>=10.10.0'}
+ hasBin: true
+ dependencies:
+ debug: 4.3.4
+ graceful-fs: 4.2.10
+ minimatch: 5.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /fraction.js/4.2.0:
+ resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
+ dev: false
+
+ /fs.realpath/1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents/2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
+ /function-bind/1.1.1:
+ resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
+
+ /function.prototype.name/1.1.5:
+ resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ es-abstract: 1.20.1
+ functions-have-names: 1.2.3
+ dev: true
+
+ /functional-red-black-tree/1.0.1:
+ resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==}
+ dev: true
+
+ /functions-have-names/1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /get-intrinsic/1.1.2:
+ resolution: {integrity: sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==}
+ dependencies:
+ function-bind: 1.1.1
+ has: 1.0.3
+ has-symbols: 1.0.3
+
+ /get-symbol-description/1.0.0:
+ resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.1.2
+ dev: true
+
+ /glob-parent/5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob-parent/6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob/7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /global-modules/2.0.0:
+ resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==}
+ engines: {node: '>=6'}
+ dependencies:
+ global-prefix: 3.0.0
+ dev: true
+
+ /global-prefix/3.0.0:
+ resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==}
+ engines: {node: '>=6'}
+ dependencies:
+ ini: 1.3.8
+ kind-of: 6.0.3
+ which: 1.3.1
+ dev: true
+
+ /globals/13.17.0:
+ resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.20.2
+ dev: true
+
+ /globby/11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.2.11
+ ignore: 5.2.0
+ merge2: 1.4.1
+ slash: 3.0.0
+ dev: true
+
+ /globjoin/0.1.4:
+ resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==}
+ dev: true
+
+ /graceful-fs/4.2.10:
+ resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
+ dev: false
+
+ /grapheme-splitter/1.0.4:
+ resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
+ dev: true
+
+ /hard-rejection/2.1.0:
+ resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /has-bigints/1.0.2:
+ resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ dev: true
+
+ /has-flag/3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /has-flag/4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors/1.0.0:
+ resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
+ dependencies:
+ get-intrinsic: 1.1.2
+ dev: true
+
+ /has-symbols/1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+
+ /has-tostringtag/1.0.0:
+ resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+
+ /has/1.0.3:
+ resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ function-bind: 1.1.1
+
+ /hasha/5.2.2:
+ resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ is-stream: 2.0.1
+ type-fest: 0.8.1
+ dev: false
+
+ /hosted-git-info/2.8.9:
+ resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
+ dev: true
+
+ /hosted-git-info/4.1.0:
+ resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
+ engines: {node: '>=10'}
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /html-tags/3.2.0:
+ resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ignore/5.2.0:
+ resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /import-fresh/3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /import-lazy/4.0.0:
+ resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /imurmurhash/0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+ dev: true
+
+ /indent-string/4.0.0:
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /inflight/1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits/2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /ini/1.3.8:
+ resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+ dev: true
+
+ /internal-slot/1.0.3:
+ resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.1.2
+ has: 1.0.3
+ side-channel: 1.0.4
+ dev: true
+
+ /is-arrayish/0.2.1:
+ resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+ dev: true
+
+ /is-bigint/1.0.4:
+ resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ dependencies:
+ has-bigints: 1.0.2
+ dev: true
+
+ /is-binary-path/2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-boolean-object/1.1.2:
+ resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-callable/1.2.4:
+ resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-core-module/2.10.0:
+ resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
+ dependencies:
+ has: 1.0.3
+
+ /is-date-object/1.0.5:
+ resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-docker/2.2.1:
+ resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dev: false
+
+ /is-expression/4.0.0:
+ resolution: {integrity: sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==}
+ dependencies:
+ acorn: 7.4.1
+ object-assign: 4.1.1
+ dev: false
+
+ /is-extglob/2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-fullwidth-code-point/3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-glob/4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-negative-zero/2.0.2:
+ resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-number-object/1.0.7:
+ resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-number/7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /is-plain-obj/1.1.0:
+ resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-plain-object/5.0.0:
+ resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-promise/2.2.2:
+ resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
+ dev: false
+
+ /is-regex/1.1.4:
+ resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ has-tostringtag: 1.0.0
+
+ /is-shared-array-buffer/1.0.2:
+ resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ dependencies:
+ call-bind: 1.0.2
+ dev: true
+
+ /is-stream/2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+ dev: false
+
+ /is-string/1.0.7:
+ resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-symbol/1.0.4:
+ resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /is-weakref/1.0.2:
+ resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ dependencies:
+ call-bind: 1.0.2
+ dev: true
+
+ /is-wsl/2.2.0:
+ resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
+ engines: {node: '>=8'}
+ dependencies:
+ is-docker: 2.2.1
+ dev: false
+
+ /isexe/2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /js-stringify/1.0.2:
+ resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==}
+ dev: false
+
+ /js-tokens/4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ dev: true
+
+ /js-yaml/4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /json-parse-even-better-errors/2.3.1:
+ resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+ dev: true
+
+ /json-schema-traverse/0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ dev: true
+
+ /json-schema-traverse/1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+ dev: true
+
+ /json-stable-stringify-without-jsonify/1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ dev: true
+
+ /json5/1.0.1:
+ resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==}
+ hasBin: true
+ dependencies:
+ minimist: 1.2.6
+ dev: true
+
+ /jstransformer-markdown-it/3.0.0:
+ resolution: {integrity: sha512-/2fNT0ir/D0NYI5roBTVRwDV2YBjMfU3f/wSeraKLfOMNxcrIJatjJQy4zPmwQBxqKxUojXBN8hmfQBMTLZ3KA==}
+ engines: {node: '>=7'}
+ dependencies:
+ markdown-it: 13.0.1
+ dev: false
+
+ /jstransformer/1.0.0:
+ resolution: {integrity: sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=}
+ dependencies:
+ is-promise: 2.2.2
+ promise: 7.3.1
+ dev: false
+
+ /kind-of/6.0.3:
+ resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /known-css-properties/0.25.0:
+ resolution: {integrity: sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==}
+ dev: true
+
+ /levn/0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /lilconfig/2.0.6:
+ resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /lines-and-columns/1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ dev: true
+
+ /linkify-it/4.0.1:
+ resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==}
+ dependencies:
+ uc.micro: 1.0.6
+ dev: false
+
+ /locate-path/5.0.0:
+ resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+ engines: {node: '>=8'}
+ dependencies:
+ p-locate: 4.1.0
+ dev: true
+
+ /locate-path/6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash.merge/4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ dev: true
+
+ /lodash.truncate/4.4.2:
+ resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==}
+ dev: true
+
+ /lru-cache/6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /map-obj/1.0.1:
+ resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /map-obj/4.3.0:
+ resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /markdown-it/13.0.1:
+ resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ entities: 3.0.1
+ linkify-it: 4.0.1
+ mdurl: 1.0.1
+ uc.micro: 1.0.6
+ dev: false
+
+ /mathml-tag-names/2.1.3:
+ resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
+ dev: true
+
+ /mdn-data/2.0.14:
+ resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
+ dev: true
+
+ /mdurl/1.0.1:
+ resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
+ dev: false
+
+ /meow/9.0.0:
+ resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ '@types/minimist': 1.2.2
+ camelcase-keys: 6.2.2
+ decamelize: 1.2.0
+ decamelize-keys: 1.1.0
+ hard-rejection: 2.1.0
+ minimist-options: 4.1.0
+ normalize-package-data: 3.0.3
+ read-pkg-up: 7.0.1
+ redent: 3.0.0
+ trim-newlines: 3.0.1
+ type-fest: 0.18.1
+ yargs-parser: 20.2.9
+ dev: true
+
+ /merge2/1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromatch/4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /min-indent/1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /minimatch/3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch/5.0.1:
+ resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==}
+ engines: {node: '>=10'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: false
+
+ /minimist-options/4.1.0:
+ resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
+ engines: {node: '>= 6'}
+ dependencies:
+ arrify: 1.0.1
+ is-plain-obj: 1.1.0
+ kind-of: 6.0.3
+ dev: true
+
+ /minimist/1.2.6:
+ resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==}
+ dev: true
+
+ /mkdirp/1.0.4:
+ resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dev: true
+
+ /ms/2.0.0:
+ resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+ dev: true
+
+ /ms/2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+ /ms/2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ dev: true
+
+ /nano-staged/0.8.0:
+ resolution: {integrity: sha512-QSEqPGTCJbkHU2yLvfY6huqYPjdBrOaTMKatO1F8nCSrkQGXeKwtCiCnsdxnuMhbg3DTVywKaeWLGCE5oJpq0g==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ picocolors: 1.0.0
+ dev: true
+
+ /nanoid/3.3.4:
+ resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ /nanospinner/1.1.0:
+ resolution: {integrity: sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA==}
+ dependencies:
+ picocolors: 1.0.0
+ dev: true
+
+ /natural-compare/1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ dev: true
+
+ /node-releases/2.0.6:
+ resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
+ dev: false
+
+ /normalize-package-data/2.5.0:
+ resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
+ dependencies:
+ hosted-git-info: 2.8.9
+ resolve: 1.22.1
+ semver: 5.7.1
+ validate-npm-package-license: 3.0.4
+ dev: true
+
+ /normalize-package-data/3.0.3:
+ resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==}
+ engines: {node: '>=10'}
+ dependencies:
+ hosted-git-info: 4.1.0
+ is-core-module: 2.10.0
+ semver: 7.3.7
+ validate-npm-package-license: 3.0.4
+ dev: true
+
+ /normalize-path/3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /normalize-range/0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
+ /nth-check/2.1.1:
+ resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+ dependencies:
+ boolbase: 1.0.0
+ dev: true
+
+ /object-assign/4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
+ /object-inspect/1.12.2:
+ resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==}
+ dev: true
+
+ /object-keys/1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign/4.1.3:
+ resolution: {integrity: sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ has-symbols: 1.0.3
+ object-keys: 1.1.1
+ dev: true
+
+ /object.values/1.1.5:
+ resolution: {integrity: sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ es-abstract: 1.20.1
+ dev: true
+
+ /once/1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /open/8.4.0:
+ resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==}
+ engines: {node: '>=12'}
+ dependencies:
+ define-lazy-prop: 2.0.0
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+ dev: false
+
+ /optionator/0.9.1:
+ resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.3
+ dev: true
+
+ /p-limit/2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+ dependencies:
+ p-try: 2.2.0
+ dev: true
+
+ /p-limit/3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-locate/4.1.0:
+ resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+ engines: {node: '>=8'}
+ dependencies:
+ p-limit: 2.3.0
+ dev: true
+
+ /p-locate/5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /p-try/2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /parent-module/1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /parse-json/5.2.0:
+ resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+ engines: {node: '>=8'}
+ dependencies:
+ '@babel/code-frame': 7.18.6
+ error-ex: 1.3.2
+ json-parse-even-better-errors: 2.3.1
+ lines-and-columns: 1.2.4
+ dev: true
+
+ /path-exists/4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute/1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key/3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-parse/1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ /path-type/4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /picocolors/1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+
+ /picomatch/2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /postcss-media-minmax/5.0.0_postcss@8.4.16:
+ resolution: {integrity: sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ postcss: 8.4.16
+ dev: false
+
+ /postcss-media-query-parser/0.2.3:
+ resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==}
+ dev: true
+
+ /postcss-nesting/10.1.10_postcss@8.4.16:
+ resolution: {integrity: sha512-lqd7LXCq0gWc0wKXtoKDru5wEUNjm3OryLVNRZ8OnW8km6fSNUuFrjEhU3nklxXE2jvd4qrox566acgh+xQt8w==}
+ engines: {node: ^12 || ^14 || >=16}
+ peerDependencies:
+ postcss: ^8.2
+ dependencies:
+ '@csstools/selector-specificity': 2.0.2_pnx64jze6bptzcedy5bidi3zdi
+ postcss: 8.4.16
+ postcss-selector-parser: 6.0.10
+ dev: false
+
+ /postcss-opacity-percentage/1.1.2:
+ resolution: {integrity: sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==}
+ engines: {node: ^12 || ^14 || >=16}
+ dev: false
+
+ /postcss-resolve-nested-selector/0.1.1:
+ resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==}
+ dev: true
+
+ /postcss-safe-parser/6.0.0_postcss@8.4.16:
+ resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.3.3
+ dependencies:
+ postcss: 8.4.16
+ dev: true
+
+ /postcss-selector-parser/6.0.10:
+ resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ /postcss-sorting/7.0.1_postcss@8.4.16:
+ resolution: {integrity: sha512-iLBFYz6VRYyLJEJsBJ8M3TCqNcckVzz4wFounSc5Oez35ogE/X+aoC5fFu103Ot7NyvjU3/xqIXn93Gp3kJk4g==}
+ peerDependencies:
+ postcss: ^8.3.9
+ dependencies:
+ postcss: 8.4.16
+ dev: true
+
+ /postcss-value-parser/4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
+ /postcss/8.4.16:
+ resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.4
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+
+ /prelude-ls/1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+ dev: true
+
+ /prettier/2.7.1:
+ resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ dev: true
+
+ /promise/7.3.1:
+ resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
+ dependencies:
+ asap: 2.0.6
+ dev: false
+
+ /pug-attrs/3.0.0:
+ resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==}
+ dependencies:
+ constantinople: 4.0.1
+ js-stringify: 1.0.2
+ pug-runtime: 3.0.1
+ dev: false
+
+ /pug-code-gen/3.0.2:
+ resolution: {integrity: sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==}
+ dependencies:
+ constantinople: 4.0.1
+ doctypes: 1.1.0
+ js-stringify: 1.0.2
+ pug-attrs: 3.0.0
+ pug-error: 2.0.0
+ pug-runtime: 3.0.1
+ void-elements: 3.1.0
+ with: 7.0.2
+ dev: false
+
+ /pug-error/2.0.0:
+ resolution: {integrity: sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==}
+ dev: false
+
+ /pug-filters/4.0.0:
+ resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==}
+ dependencies:
+ constantinople: 4.0.1
+ jstransformer: 1.0.0
+ pug-error: 2.0.0
+ pug-walk: 2.0.0
+ resolve: 1.22.1
+ dev: false
+
+ /pug-lexer/5.0.1:
+ resolution: {integrity: sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==}
+ dependencies:
+ character-parser: 2.2.0
+ is-expression: 4.0.0
+ pug-error: 2.0.0
+ dev: false
+
+ /pug-linker/4.0.0:
+ resolution: {integrity: sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==}
+ dependencies:
+ pug-error: 2.0.0
+ pug-walk: 2.0.0
+ dev: false
+
+ /pug-load/3.0.0:
+ resolution: {integrity: sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==}
+ dependencies:
+ object-assign: 4.1.1
+ pug-walk: 2.0.0
+ dev: false
+
+ /pug-parser/6.0.0:
+ resolution: {integrity: sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==}
+ dependencies:
+ pug-error: 2.0.0
+ token-stream: 1.0.0
+ dev: false
+
+ /pug-runtime/3.0.1:
+ resolution: {integrity: sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==}
+ dev: false
+
+ /pug-strip-comments/2.0.0:
+ resolution: {integrity: sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==}
+ dependencies:
+ pug-error: 2.0.0
+ dev: false
+
+ /pug-walk/2.0.0:
+ resolution: {integrity: sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==}
+ dev: false
+
+ /pug/3.0.2:
+ resolution: {integrity: sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==}
+ dependencies:
+ pug-code-gen: 3.0.2
+ pug-filters: 4.0.0
+ pug-lexer: 5.0.1
+ pug-linker: 4.0.0
+ pug-load: 3.0.0
+ pug-parser: 6.0.0
+ pug-runtime: 3.0.1
+ pug-strip-comments: 2.0.0
+ dev: false
+
+ /punycode/2.1.1:
+ resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /queue-microtask/1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /quick-lru/4.0.1:
+ resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /read-pkg-up/7.0.1:
+ resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
+ engines: {node: '>=8'}
+ dependencies:
+ find-up: 4.1.0
+ read-pkg: 5.2.0
+ type-fest: 0.8.1
+ dev: true
+
+ /read-pkg/5.2.0:
+ resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
+ engines: {node: '>=8'}
+ dependencies:
+ '@types/normalize-package-data': 2.4.1
+ normalize-package-data: 2.5.0
+ parse-json: 5.2.0
+ type-fest: 0.6.0
+ dev: true
+
+ /readdirp/3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /redent/3.0.0:
+ resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
+ engines: {node: '>=8'}
+ dependencies:
+ indent-string: 4.0.0
+ strip-indent: 3.0.0
+ dev: true
+
+ /regexp.prototype.flags/1.4.3:
+ resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ functions-have-names: 1.2.3
+ dev: true
+
+ /regexpp/3.2.0:
+ resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /require-from-string/2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /requireindex/1.2.0:
+ resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==}
+ engines: {node: '>=0.10.5'}
+ dev: true
+
+ /resolve-from/4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve-from/5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /resolve/1.22.1:
+ resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.10.0
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ /reusify/1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rimraf/3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /rollup/2.77.3:
+ resolution: {integrity: sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: false
+
+ /run-parallel/1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /semver/5.7.1:
+ resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
+ hasBin: true
+ dev: true
+
+ /semver/7.3.7:
+ resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /shebang-command/2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex/3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /side-channel/1.0.4:
+ resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.1.2
+ object-inspect: 1.12.2
+ dev: true
+
+ /signal-exit/3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+ dev: true
+
+ /simple-git-hooks/2.8.0:
+ resolution: {integrity: sha512-ocmZQORwa6x9mxg+gVIAp5o4wXiWOHGXyrDBA0+UxGKIEKOyFtL4LWNKkP/2ornQPdlnlDGDteVeYP5FjhIoWA==}
+ hasBin: true
+ requiresBuild: true
+ dev: true
+
+ /size-limit/8.0.1:
+ resolution: {integrity: sha512-VHrozqkQTYfcv1OlZIRIL0x6f+xhZ3TT+RTXC5AvKn/yA+3PIWERrKWqHMJPD7G/Vi0SuBtWAn3IvCGx2/UB1g==}
+ engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
+ hasBin: true
+ dependencies:
+ bytes-iec: 3.1.1
+ chokidar: 3.5.3
+ ci-job-number: 1.2.2
+ globby: 11.1.0
+ lilconfig: 2.0.6
+ mkdirp: 1.0.4
+ nanospinner: 1.1.0
+ picocolors: 1.0.0
+ dev: true
+
+ /slash/3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /slice-ansi/4.0.0:
+ resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ astral-regex: 2.0.0
+ is-fullwidth-code-point: 3.0.0
+ dev: true
+
+ /source-map-js/1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+
+ /source-map/0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /spdx-correct/3.1.1:
+ resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==}
+ dependencies:
+ spdx-expression-parse: 3.0.1
+ spdx-license-ids: 3.0.11
+ dev: true
+
+ /spdx-exceptions/2.3.0:
+ resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
+ dev: true
+
+ /spdx-expression-parse/3.0.1:
+ resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
+ dependencies:
+ spdx-exceptions: 2.3.0
+ spdx-license-ids: 3.0.11
+ dev: true
+
+ /spdx-license-ids/3.0.11:
+ resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==}
+ dev: true
+
+ /ssdeploy/0.9.1:
+ resolution: {integrity: sha512-4jfgSGlpKGBLQcva72Vo33CSW9VlHmEaAZ4WV8hgTEL8mnOsdxOYYZlxq2+hwtHrmPVdML4A0cOHAy6bmhGI9w==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ bytes: 3.1.2
+ dotenv: 16.0.1
+ folder-hash: 4.0.2
+ hasha: 5.2.2
+ open: 8.4.0
+ picocolors: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /stable/0.1.8:
+ resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
+ deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
+ dev: true
+
+ /string-width/4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /string.prototype.trimend/1.0.5:
+ resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ es-abstract: 1.20.1
+ dev: true
+
+ /string.prototype.trimstart/1.0.5:
+ resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.1.4
+ es-abstract: 1.20.1
+ dev: true
+
+ /strip-ansi/6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /strip-bom/3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /strip-indent/3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ min-indent: 1.0.1
+ dev: true
+
+ /strip-json-comments/3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /style-search/0.1.0:
+ resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==}
+ dev: true
+
+ /stylelint-config-recess-order/3.0.0_stylelint@14.10.0:
+ resolution: {integrity: sha512-uNXrlDz570Q7HJlrq8mNjgfO/xlKIh2hKVKEFMTG1/ih/6tDLcTbuvO1Zoo2dnQay990OAkWLDpTDOorB+hmBw==}
+ peerDependencies:
+ stylelint: '>=14'
+ dependencies:
+ stylelint: 14.10.0
+ stylelint-order: 5.0.0_stylelint@14.10.0
+ dev: true
+
+ /stylelint-config-recommended/7.0.0_stylelint@14.10.0:
+ resolution: {integrity: sha512-yGn84Bf/q41J4luis1AZ95gj0EQwRX8lWmGmBwkwBNSkpGSpl66XcPTulxGa/Z91aPoNGuIGBmFkcM1MejMo9Q==}
+ peerDependencies:
+ stylelint: ^14.4.0
+ dependencies:
+ stylelint: 14.10.0
+ dev: true
+
+ /stylelint-config-standard/25.0.0_stylelint@14.10.0:
+ resolution: {integrity: sha512-21HnP3VSpaT1wFjFvv9VjvOGDtAviv47uTp3uFmzcN+3Lt+RYRv6oAplLaV51Kf792JSxJ6svCJh/G18E9VnCA==}
+ peerDependencies:
+ stylelint: ^14.4.0
+ dependencies:
+ stylelint: 14.10.0
+ stylelint-config-recommended: 7.0.0_stylelint@14.10.0
+ dev: true
+
+ /stylelint-order/5.0.0_stylelint@14.10.0:
+ resolution: {integrity: sha512-OWQ7pmicXufDw5BlRqzdz3fkGKJPgLyDwD1rFY3AIEfIH/LQY38Vu/85v8/up0I+VPiuGRwbc2Hg3zLAsJaiyw==}
+ peerDependencies:
+ stylelint: ^14.0.0
+ dependencies:
+ postcss: 8.4.16
+ postcss-sorting: 7.0.1_postcss@8.4.16
+ stylelint: 14.10.0
+ dev: true
+
+ /stylelint/14.10.0:
+ resolution: {integrity: sha512-VAmyKrEK+wNFh9R8mNqoxEFzaa4gsHGhcT4xgkQDuOA5cjF6CaNS8loYV7gpi4tIZBPUyXesotPXzJAMN8VLOQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@csstools/selector-specificity': 2.0.2_pnx64jze6bptzcedy5bidi3zdi
+ balanced-match: 2.0.0
+ colord: 2.9.3
+ cosmiconfig: 7.0.1
+ css-functions-list: 3.1.0
+ debug: 4.3.4
+ fast-glob: 3.2.11
+ fastest-levenshtein: 1.0.16
+ file-entry-cache: 6.0.1
+ global-modules: 2.0.0
+ globby: 11.1.0
+ globjoin: 0.1.4
+ html-tags: 3.2.0
+ ignore: 5.2.0
+ import-lazy: 4.0.0
+ imurmurhash: 0.1.4
+ is-plain-object: 5.0.0
+ known-css-properties: 0.25.0
+ mathml-tag-names: 2.1.3
+ meow: 9.0.0
+ micromatch: 4.0.5
+ normalize-path: 3.0.0
+ picocolors: 1.0.0
+ postcss: 8.4.16
+ postcss-media-query-parser: 0.2.3
+ postcss-resolve-nested-selector: 0.1.1
+ postcss-safe-parser: 6.0.0_postcss@8.4.16
+ postcss-selector-parser: 6.0.10
+ postcss-value-parser: 4.2.0
+ resolve-from: 5.0.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ style-search: 0.1.0
+ supports-hyperlinks: 2.2.0
+ svg-tags: 1.0.0
+ table: 6.8.0
+ v8-compile-cache: 2.3.0
+ write-file-atomic: 4.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /supports-color/5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+ dependencies:
+ has-flag: 3.0.0
+ dev: true
+
+ /supports-color/7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-hyperlinks/2.2.0:
+ resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ supports-color: 7.2.0
+ dev: true
+
+ /supports-preserve-symlinks-flag/1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ /svg-tags/1.0.0:
+ resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
+ dev: true
+
+ /svgo/2.8.0:
+ resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ dependencies:
+ '@trysound/sax': 0.2.0
+ commander: 7.2.0
+ css-select: 4.3.0
+ css-tree: 1.1.3
+ csso: 4.2.0
+ picocolors: 1.0.0
+ stable: 0.1.8
+ dev: true
+
+ /table/6.8.0:
+ resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==}
+ engines: {node: '>=10.0.0'}
+ dependencies:
+ ajv: 8.11.0
+ lodash.truncate: 4.4.2
+ slice-ansi: 4.0.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /text-table/0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ dev: true
+
+ /to-fast-properties/2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: false
+
+ /to-regex-range/5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /token-stream/1.0.0:
+ resolution: {integrity: sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=}
+ dev: false
+
+ /trim-newlines/3.0.1:
+ resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /tsconfig-paths/3.14.1:
+ resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==}
+ dependencies:
+ '@types/json5': 0.0.29
+ json5: 1.0.1
+ minimist: 1.2.6
+ strip-bom: 3.0.0
+ dev: true
+
+ /tslib/1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+ dev: true
+
+ /tsutils/3.21.0_typescript@4.7.4:
+ resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
+ 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'
+ dependencies:
+ tslib: 1.14.1
+ typescript: 4.7.4
+ dev: true
+
+ /type-check/0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ dev: true
+
+ /type-fest/0.18.1:
+ resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /type-fest/0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /type-fest/0.6.0:
+ resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /type-fest/0.8.1:
+ resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
+ engines: {node: '>=8'}
+
+ /typescript/4.7.4:
+ resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
+
+ /uc.micro/1.0.6:
+ resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
+ dev: false
+
+ /unbox-primitive/1.0.2:
+ resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ dependencies:
+ call-bind: 1.0.2
+ has-bigints: 1.0.2
+ has-symbols: 1.0.3
+ which-boxed-primitive: 1.0.2
+ dev: true
+
+ /update-browserslist-db/1.0.5_browserslist@4.21.3:
+ resolution: {integrity: sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.21.3
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: false
+
+ /uri-js/4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.1.1
+ dev: true
+
+ /util-deprecate/1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ /v8-compile-cache/2.3.0:
+ resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==}
+ dev: true
+
+ /validate-npm-package-license/3.0.4:
+ resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
+ dependencies:
+ spdx-correct: 3.1.1
+ spdx-expression-parse: 3.0.1
+ dev: true
+
+ /vite-plugin-pug-transformer/1.0.2_vite@3.0.7:
+ resolution: {integrity: sha512-RtXEYaEgQoy5ttNjuuNMWRzZwfJz+cjePSdQzmNJTteIzUamVb8xvAlwNouMt189V2mk6HxyfTGfAGKUQ6KGig==}
+ engines: {node: '>=12.22.0'}
+ peerDependencies:
+ vite: ^2.5.10 || ^3.0.0
+ dependencies:
+ picocolors: 1.0.0
+ pug: 3.0.2
+ vite: 3.0.7
+ dev: false
+
+ /vite/3.0.7:
+ resolution: {integrity: sha512-dILhvKba1mbP1wCezVQx/qhEK7/+jVn9ciadEcyKMMhZpsuAi/eWZfJRMkmYlkSFG7Qq9NvJbgFq4XOBxugJsA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ esbuild: 0.14.54
+ postcss: 8.4.16
+ resolve: 1.22.1
+ rollup: 2.77.3
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: false
+
+ /void-elements/3.1.0:
+ resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
+ /which-boxed-primitive/1.0.2:
+ resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ dependencies:
+ is-bigint: 1.0.4
+ is-boolean-object: 1.1.2
+ is-number-object: 1.0.7
+ is-string: 1.0.7
+ is-symbol: 1.0.4
+ dev: true
+
+ /which/1.3.1:
+ resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /which/2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /with/7.0.2:
+ resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==}
+ engines: {node: '>= 10.0.0'}
+ dependencies:
+ '@babel/parser': 7.18.11
+ '@babel/types': 7.18.10
+ assert-never: 1.2.1
+ babel-walk: 3.0.0-canary-5
+ dev: false
+
+ /word-wrap/1.2.3:
+ resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /wrappy/1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /write-file-atomic/4.0.1:
+ resolution: {integrity: sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==}
+ engines: {node: ^12.13.0 || ^14.15.0 || >=16}
+ dependencies:
+ imurmurhash: 0.1.4
+ signal-exit: 3.0.7
+ dev: true
+
+ /yallist/4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ dev: true
+
+ /yaml/1.10.2:
+ resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /yargs-parser/20.2.9:
+ resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yocto-queue/0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 00000000..b2eff6c8
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+packages:
+ - client
+ - server
diff --git a/public/images/and_chr.png b/public/images/and_chr.png
deleted file mode 120000
index da47ce43..00000000
--- a/public/images/and_chr.png
+++ /dev/null
@@ -1 +0,0 @@
-chrome.png
\ No newline at end of file
diff --git a/public/images/and_ff.png b/public/images/and_ff.png
deleted file mode 120000
index 93c4678c..00000000
--- a/public/images/and_ff.png
+++ /dev/null
@@ -1 +0,0 @@
-firefox.png
\ No newline at end of file
diff --git a/public/images/and_qq.png b/public/images/and_qq.png
deleted file mode 100644
index 6094b5ec..00000000
Binary files a/public/images/and_qq.png and /dev/null differ
diff --git a/public/images/and_uc.png b/public/images/and_uc.png
deleted file mode 120000
index e21e353b..00000000
--- a/public/images/and_uc.png
+++ /dev/null
@@ -1 +0,0 @@
-uc.png
\ No newline at end of file
diff --git a/public/images/android-webview-beta.png b/public/images/android-webview-beta.png
deleted file mode 100755
index f751068f..00000000
Binary files a/public/images/android-webview-beta.png and /dev/null differ
diff --git a/public/images/android.png b/public/images/android.png
deleted file mode 100755
index 6808a366..00000000
Binary files a/public/images/android.png and /dev/null differ
diff --git a/public/images/baidu.png b/public/images/baidu.png
deleted file mode 100644
index 0919dd0d..00000000
Binary files a/public/images/baidu.png and /dev/null differ
diff --git a/public/images/bb.png b/public/images/bb.png
deleted file mode 100755
index 80dfae0a..00000000
Binary files a/public/images/bb.png and /dev/null differ
diff --git a/public/images/chrome-beta.png b/public/images/chrome-beta.png
deleted file mode 100755
index 5cbdff63..00000000
Binary files a/public/images/chrome-beta.png and /dev/null differ
diff --git a/public/images/chrome-canary.png b/public/images/chrome-canary.png
deleted file mode 100755
index 8a9d415f..00000000
Binary files a/public/images/chrome-canary.png and /dev/null differ
diff --git a/public/images/chrome-dev.png b/public/images/chrome-dev.png
deleted file mode 100755
index e3330331..00000000
Binary files a/public/images/chrome-dev.png and /dev/null differ
diff --git a/public/images/chrome.png b/public/images/chrome.png
deleted file mode 100755
index eaaddc6e..00000000
Binary files a/public/images/chrome.png and /dev/null differ
diff --git a/public/images/edge-tile.png b/public/images/edge-tile.png
deleted file mode 100755
index 28aeece1..00000000
Binary files a/public/images/edge-tile.png and /dev/null differ
diff --git a/public/images/edge.png b/public/images/edge.png
deleted file mode 100755
index 87cfb29e..00000000
Binary files a/public/images/edge.png and /dev/null differ
diff --git a/public/images/favicon.png b/public/images/favicon.png
deleted file mode 100644
index 1dea7736..00000000
Binary files a/public/images/favicon.png and /dev/null differ
diff --git a/public/images/firefox-beta.png b/public/images/firefox-beta.png
deleted file mode 100755
index e824f09c..00000000
Binary files a/public/images/firefox-beta.png and /dev/null differ
diff --git a/public/images/firefox-developer-edition.png b/public/images/firefox-developer-edition.png
deleted file mode 100755
index e38fe35a..00000000
Binary files a/public/images/firefox-developer-edition.png and /dev/null differ
diff --git a/public/images/firefox-nightly.png b/public/images/firefox-nightly.png
deleted file mode 100755
index e4de3fb8..00000000
Binary files a/public/images/firefox-nightly.png and /dev/null differ
diff --git a/public/images/firefox.png b/public/images/firefox.png
deleted file mode 100755
index e9d7facd..00000000
Binary files a/public/images/firefox.png and /dev/null differ
diff --git a/public/images/ie.png b/public/images/ie.png
deleted file mode 120000
index 07642c1f..00000000
--- a/public/images/ie.png
+++ /dev/null
@@ -1 +0,0 @@
-internet-explorer.png
\ No newline at end of file
diff --git a/public/images/ie_mob.png b/public/images/ie_mob.png
deleted file mode 120000
index e0e452ba..00000000
--- a/public/images/ie_mob.png
+++ /dev/null
@@ -1 +0,0 @@
-internet-explorer-tile.png
\ No newline at end of file
diff --git a/public/images/internet-explorer-tile.png b/public/images/internet-explorer-tile.png
deleted file mode 100755
index d5ab8a3e..00000000
Binary files a/public/images/internet-explorer-tile.png and /dev/null differ
diff --git a/public/images/internet-explorer.png b/public/images/internet-explorer.png
deleted file mode 100755
index 51b26d2b..00000000
Binary files a/public/images/internet-explorer.png and /dev/null differ
diff --git a/public/images/ios_saf.png b/public/images/ios_saf.png
deleted file mode 120000
index 198bfab3..00000000
--- a/public/images/ios_saf.png
+++ /dev/null
@@ -1 +0,0 @@
-safari-ios.png
\ No newline at end of file
diff --git a/public/images/kaios.png b/public/images/kaios.png
deleted file mode 100644
index 908ce92f..00000000
Binary files a/public/images/kaios.png and /dev/null differ
diff --git a/public/images/node.png b/public/images/node.png
deleted file mode 100644
index 0d2013dc..00000000
Binary files a/public/images/node.png and /dev/null differ
diff --git a/public/images/op_mini.png b/public/images/op_mini.png
deleted file mode 120000
index 01e8a63a..00000000
--- a/public/images/op_mini.png
+++ /dev/null
@@ -1 +0,0 @@
-opera-mini.png
\ No newline at end of file
diff --git a/public/images/op_mob.png b/public/images/op_mob.png
deleted file mode 120000
index 01e8a63a..00000000
--- a/public/images/op_mob.png
+++ /dev/null
@@ -1 +0,0 @@
-opera-mini.png
\ No newline at end of file
diff --git a/public/images/opera-beta.png b/public/images/opera-beta.png
deleted file mode 100755
index 03e0b891..00000000
Binary files a/public/images/opera-beta.png and /dev/null differ
diff --git a/public/images/opera-developer.png b/public/images/opera-developer.png
deleted file mode 100755
index 09e69c8e..00000000
Binary files a/public/images/opera-developer.png and /dev/null differ
diff --git a/public/images/opera-mini-beta.png b/public/images/opera-mini-beta.png
deleted file mode 100755
index 54c7b7f1..00000000
Binary files a/public/images/opera-mini-beta.png and /dev/null differ
diff --git a/public/images/opera-mini.png b/public/images/opera-mini.png
deleted file mode 100755
index 85afada4..00000000
Binary files a/public/images/opera-mini.png and /dev/null differ
diff --git a/public/images/opera.png b/public/images/opera.png
deleted file mode 100755
index 78f71717..00000000
Binary files a/public/images/opera.png and /dev/null differ
diff --git a/public/images/safari-ios.png b/public/images/safari-ios.png
deleted file mode 100755
index 8f6ab13d..00000000
Binary files a/public/images/safari-ios.png and /dev/null differ
diff --git a/public/images/safari-technology-preview.png b/public/images/safari-technology-preview.png
deleted file mode 100755
index 5f512fb2..00000000
Binary files a/public/images/safari-technology-preview.png and /dev/null differ
diff --git a/public/images/safari.png b/public/images/safari.png
deleted file mode 100755
index 96373e24..00000000
Binary files a/public/images/safari.png and /dev/null differ
diff --git a/public/images/samsung-internet.png b/public/images/samsung-internet.png
deleted file mode 100755
index b2efaccc..00000000
Binary files a/public/images/samsung-internet.png and /dev/null differ
diff --git a/public/images/samsung.png b/public/images/samsung.png
deleted file mode 120000
index 169b71b3..00000000
--- a/public/images/samsung.png
+++ /dev/null
@@ -1 +0,0 @@
-samsung-internet.png
\ No newline at end of file
diff --git a/public/images/uc.png b/public/images/uc.png
deleted file mode 100755
index 0091d6c8..00000000
Binary files a/public/images/uc.png and /dev/null differ
diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css
deleted file mode 100644
index 4acb8040..00000000
--- a/public/stylesheets/style.css
+++ /dev/null
@@ -1,25 +0,0 @@
-body {
- color: #111;
- background-color: #fff;
-}
-
-a {
- font-weight: bold;
- text-decoration: none;
- color: #490245;
-}
-
-a:hover {
- text-decoration: underline;
-}
-
-.neon-carrot { color: #fda34f; }
-.plum { color: #490245; }
-.bg-neon-carrot { background-color: #fda34f; }
-.bg-plum { background-color: #490245; }
-.dt-ns ::selection { background: #ffcc00; }
-.lh-copy ::selection { background: #ffcc00; }
-
-.bg-plum--hover:hover {
- background-color: #260024;
-}
diff --git a/public/stylesheets/tachyons.min.css b/public/stylesheets/tachyons.min.css
deleted file mode 100644
index ed7da41f..00000000
--- a/public/stylesheets/tachyons.min.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}button,input,optgroup,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.border-box,article,body,code,dd,div,dl,dt,fieldset,footer,form,header,html,input[type=email],input[type=number],input[type=password],input[type=tel],input[type=text],input[type=url],li,main,ol,p,pre,section,textarea,ul{box-sizing:border-box}.cover{background-size:cover}.contain{background-size:contain}.ba{border-style:solid;border-width:1px}.bt{border-top-style:solid;border-top-width:1px}.br{border-right-style:solid;border-right-width:1px}.bb{border-bottom-style:solid;border-bottom-width:1px}.bl{border-left-style:solid;border-left-width:1px}.bn{border-style:none;border-width:0}.b--black{border-color:#000}.b--near-black{border-color:#111}.b--dark-gray{border-color:#333}.b--mid-gray{border-color:#555}.b--gray{border-color:#777}.b--silver{border-color:#999}.b--light-silver{border-color:#aaa}.b--light-gray{border-color:#eee}.b--near-white{border-color:#f4f4f4}.b--white{border-color:#fff}.b--white-90{border-color:hsla(0,0%,100%,.9)}.b--white-80{border-color:hsla(0,0%,100%,.8)}.b--white-70{border-color:hsla(0,0%,100%,.7)}.b--white-60{border-color:hsla(0,0%,100%,.6)}.b--white-50{border-color:hsla(0,0%,100%,.5)}.b--white-40{border-color:hsla(0,0%,100%,.4)}.b--white-30{border-color:hsla(0,0%,100%,.3)}.b--white-20{border-color:hsla(0,0%,100%,.2)}.b--white-10{border-color:hsla(0,0%,100%,.1)}.b--white-05{border-color:hsla(0,0%,100%,.05)}.b--white-025{border-color:hsla(0,0%,100%,.025)}.b--white-0125{border-color:hsla(0,0%,100%,.0125)}.b--black-90{border-color:rgba(0,0,0,.9)}.b--black-80{border-color:rgba(0,0,0,.8)}.b--black-70{border-color:rgba(0,0,0,.7)}.b--black-60{border-color:rgba(0,0,0,.6)}.b--black-50{border-color:rgba(0,0,0,.5)}.b--black-40{border-color:rgba(0,0,0,.4)}.b--black-30{border-color:rgba(0,0,0,.3)}.b--black-20{border-color:rgba(0,0,0,.2)}.b--black-10{border-color:rgba(0,0,0,.1)}.b--black-05{border-color:rgba(0,0,0,.05)}.b--black-025{border-color:rgba(0,0,0,.025)}.b--black-0125{border-color:rgba(0,0,0,.0125)}.b--dark-red{border-color:#f00008}.b--red{border-color:#ff3223}.b--orange{border-color:#f3a801}.b--gold{border-color:#f2c800}.b--yellow{border-color:#ffde37}.b--purple{border-color:#7d5da9}.b--light-purple{border-color:#8d4f92}.b--hot-pink{border-color:#d62288}.b--dark-pink{border-color:#c64774}.b--pink{border-color:#f49cc8}.b--dark-green{border-color:#006c71}.b--green{border-color:#41d69f}.b--navy{border-color:#001b44}.b--dark-blue{border-color:#00449e}.b--blue{border-color:#357edd}.b--light-blue{border-color:#96ccff}.b--lightest-blue{border-color:#cdecff}.b--washed-blue{border-color:#f6fffe}.b--washed-green{border-color:#e8fdf5}.b--washed-yellow{border-color:#fff8d5}.b--light-pink{border-color:#efa4b8}.b--light-yellow{border-color:#f3dd70}.b--light-red{border-color:#ffd3c0}.b--transparent{border-color:transparent}.br0{border-radius:0}.br1{border-radius:.125rem}.br2{border-radius:.25rem}.br3{border-radius:.5rem}.br4{border-radius:1rem}.br-100{border-radius:100%}.br--bottom{border-top-left-radius:0;border-top-right-radius:0}.br--top{border-bottom-right-radius:0}.br--right,.br--top{border-bottom-left-radius:0}.br--right{border-top-left-radius:0}.br--left{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted{border-style:dotted}.b--dashed{border-style:dashed}.b--solid{border-style:solid}.b--none{border-style:none}.bw0{border-width:0}.bw1{border-width:.125rem}.bw2{border-width:.25rem}.bw3{border-width:.5rem}.bw4{border-width:1rem}.bw5{border-width:2rem}.bt-0{border-top-width:0}.br-0{border-right-width:0}.bb-0{border-bottom-width:0}.bl-0{border-left-width:0}.shadow-1{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.pre{overflow-x:auto;overflow-y:hidden;overflow:scroll}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.top-1{top:1rem}.right-1{right:1rem}.bottom-1{bottom:1rem}.left-1{left:1rem}.top-2{top:2rem}.right-2{right:2rem}.bottom-2{bottom:2rem}.left-2{left:2rem}.top--1{top:-1rem}.right--1{right:-1rem}.bottom--1{bottom:-1rem}.left--1{left:-1rem}.top--2{top:-2rem}.right--2{right:-2rem}.bottom--2{bottom:-2rem}.left--2{left:-2rem}.absolute--fill{top:0;right:0;bottom:0;left:0}.cf:after,.cf:before{content:" ";display:table}.cf:after{clear:both}.cf{*zoom:1}.cl{clear:left}.cr{clear:right}.cb{clear:both}.cn{clear:none}.dn{display:none}.di{display:inline}.db{display:block}.dib{display:inline-block}.dit{display:inline-table}.dt{display:table}.dtc{display:table-cell}.dt-row{display:table-row}.dt-row-group{display:table-row-group}.dt-column{display:table-column}.dt-column-group{display:table-column-group}.dt--fixed{table-layout:fixed;width:100%}.flex{display:flex}.flex-auto{flex:1 1 auto;min-width:0;min-height:0}.flex-none{flex:none}.flex-column{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.self-start{align-self:flex-start}.self-end{align-self:flex-end}.self-center{align-self:center}.self-baseline{align-self:baseline}.self-stretch{align-self:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.content-start{align-content:flex-start}.content-end{align-content:flex-end}.content-center{align-content:center}.content-between{align-content:space-between}.content-around{align-content:space-around}.content-stretch{align-content:stretch}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-last{order:99999}.fl{float:left}.fl,.fr{_display:inline}.fr{float:right}.fn{float:none}.sans-serif{font-family:-apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica,helvetica neue,ubuntu,roboto,noto,segoe ui,arial,sans-serif}.serif{font-family:georgia,times,serif}.system-sans-serif{font-family:sans-serif}.system-serif{font-family:serif}.code,code{font-family:Consolas,monaco,monospace}.helvetica{font-family:helvetica neue,helvetica,sans-serif}.avenir{font-family:avenir next,avenir,sans-serif}.georgia{font-family:georgia,serif}.times{font-family:times,serif}.bodoni{font-family:Bodoni MT,serif}.calisto{font-family:Calisto MT,serif}.baskerville,.garamond{font-family:garamond,serif}.i{font-style:italic}.fs-normal{font-style:normal}.normal{font-weight:400}.b{font-weight:700}.fw1{font-weight:100}.fw2{font-weight:200}.fw3{font-weight:300}.fw4{font-weight:400}.fw5{font-weight:500}.fw6{font-weight:600}.fw7{font-weight:700}.fw8{font-weight:800}.fw9{font-weight:900}.input-reset{-webkit-appearance:none;-moz-appearance:none}.h1{height:1rem}.h2{height:2rem}.h3{height:4rem}.h4{height:8rem}.h5{height:16rem}.h-25{height:25%}.h-50{height:50%}.h-75{height:75%}.h-100{height:100%}.h-auto{height:auto}.h-inherit{height:inherit}.tracked{letter-spacing:.16em}.tracked-tight{letter-spacing:-.05em}.tracked-mega{letter-spacing:.32em}.lh-solid{line-height:1}.lh-title{line-height:1.3}.lh-copy{line-height:1.6}.link{text-decoration:none}.link,.link:active,.link:focus,.link:hover,.link:link,.link:visited{transition:color .15s ease-in}.list{list-style-type:none}.mw-100{max-width:100%}.mw1{max-width:1rem}.mw2{max-width:2rem}.mw3{max-width:4rem}.mw4{max-width:8rem}.mw5{max-width:16rem}.mw6{max-width:32rem}.mw7{max-width:48rem}.mw8{max-width:64rem}.mw9{max-width:96rem}.mw-none{max-width:none}.w1{width:1rem}.w2{width:2rem}.w3{width:4rem}.w4{width:8rem}.w5{width:16rem}.w-10{width:10%}.w-20{width:20%}.w-25{width:25%}.w-33{width:33%}.w-34{width:34%}.w-40{width:40%}.w-50{width:50%}.w-60{width:60%}.w-75{width:75%}.w-80{width:80%}.w-100{width:100%}.w-auto{width:auto}.overflow-visible{overflow:visible}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-auto{overflow:auto}.overflow-x-visible{overflow-x:visible}.overflow-x-hidden{overflow-x:hidden}.overflow-x-scroll{overflow-x:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-visible{overflow-y:visible}.overflow-y-hidden{overflow-y:hidden}.overflow-y-scroll{overflow-y:scroll}.overflow-y-auto{overflow-y:auto}.static{position:static}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.o-100{opacity:1}.o-90{opacity:.9}.o-80{opacity:.8}.o-70{opacity:.7}.o-60{opacity:.6}.o-50{opacity:.5}.o-40{opacity:.4}.o-30{opacity:.3}.o-20{opacity:.2}.o-10{opacity:.1}.o-05{opacity:.05}.o-025{opacity:.025}.o-0{opacity:0}.black-90{color:rgba(0,0,0,.9)}.black-80{color:rgba(0,0,0,.8)}.black-70{color:rgba(0,0,0,.7)}.black-60{color:rgba(0,0,0,.6)}.black-50{color:rgba(0,0,0,.5)}.black-40{color:rgba(0,0,0,.4)}.black-30{color:rgba(0,0,0,.3)}.black-20{color:rgba(0,0,0,.2)}.black-10{color:rgba(0,0,0,.1)}.black-05{color:rgba(0,0,0,.05)}.white-90{color:hsla(0,0%,100%,.9)}.white-80{color:hsla(0,0%,100%,.8)}.white-70{color:hsla(0,0%,100%,.7)}.white-60{color:hsla(0,0%,100%,.6)}.white-50{color:hsla(0,0%,100%,.5)}.white-40{color:hsla(0,0%,100%,.4)}.white-30{color:hsla(0,0%,100%,.3)}.white-20{color:hsla(0,0%,100%,.2)}.white-10{color:hsla(0,0%,100%,.1)}.black{color:#000}.near-black{color:#111}.dark-gray{color:#333}.mid-gray{color:#555}.gray{color:#777}.silver{color:#999}.light-silver{color:#aaa}.moon-gray{color:#ccc}.light-gray{color:#eee}.near-white{color:#f4f4f4}.white{color:#fff}.dark-red{color:#f00008}.red{color:#ff3223}.orange{color:#f3a801}.gold{color:#f2c800}.yellow{color:#ffde37}.purple{color:#7d5da9}.light-purple{color:#8d4f92}.hot-pink{color:#d62288}.dark-pink{color:#c64774}.pink{color:#f49cc8}.dark-green{color:#006c71}.green{color:#41d69f}.navy{color:#001b44}.dark-blue{color:#00449e}.blue{color:#357edd}.light-blue{color:#96ccff}.lightest-blue{color:#cdecff}.washed-blue{color:#f6fffe}.washed-green{color:#e8fdf5}.washed-yellow{color:#fff8d5}.light-pink{color:#efa4b8}.light-yellow{color:#f3dd70}.light-red{color:#ffd3c0}.bg-black-90{background-color:rgba(0,0,0,.9)}.bg-black-80{background-color:rgba(0,0,0,.8)}.bg-black-70{background-color:rgba(0,0,0,.7)}.bg-black-60{background-color:rgba(0,0,0,.6)}.bg-black-50{background-color:rgba(0,0,0,.5)}.bg-black-40{background-color:rgba(0,0,0,.4)}.bg-black-30{background-color:rgba(0,0,0,.3)}.bg-black-20{background-color:rgba(0,0,0,.2)}.bg-black-10{background-color:rgba(0,0,0,.1)}.bg-black-05{background-color:rgba(0,0,0,.05)}.bg-white-90{background-color:hsla(0,0%,100%,.9)}.bg-white-80{background-color:hsla(0,0%,100%,.8)}.bg-white-70{background-color:hsla(0,0%,100%,.7)}.bg-white-60{background-color:hsla(0,0%,100%,.6)}.bg-white-50{background-color:hsla(0,0%,100%,.5)}.bg-white-40{background-color:hsla(0,0%,100%,.4)}.bg-white-30{background-color:hsla(0,0%,100%,.3)}.bg-white-20{background-color:hsla(0,0%,100%,.2)}.bg-white-10{background-color:hsla(0,0%,100%,.1)}.bg-black{background-color:#000}.bg-near-black{background-color:#111}.bg-dark-gray{background-color:#333}.bg-mid-gray{background-color:#555}.bg-gray{background-color:#777}.bg-silver{background-color:#999}.bg-light-silver{background-color:#aaa}.bg-moon-gray{background-color:#ccc}.bg-light-gray{background-color:#eee}.bg-near-white{background-color:#f4f4f4}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.bg-dark-red{background-color:#f00008}.bg-red{background-color:#ff3223}.bg-orange{background-color:#f3a801}.bg-gold{background-color:#f2c800}.bg-yellow{background-color:#ffde37}.bg-purple{background-color:#7d5da9}.bg-light-purple{background-color:#8d4f92}.bg-hot-pink{background-color:#d62288}.bg-dark-pink{background-color:#c64774}.bg-pink{background-color:#f49cc8}.bg-dark-green{background-color:#006c71}.bg-green{background-color:#41d69f}.bg-navy{background-color:#001b44}.bg-dark-blue{background-color:#00449e}.bg-blue{background-color:#357edd}.bg-light-blue{background-color:#96ccff}.bg-lightest-blue{background-color:#cdecff}.bg-washed-blue{background-color:#f6fffe}.bg-washed-green{background-color:#e8fdf5}.bg-washed-yellow{background-color:#fff8d5}.bg-light-pink{background-color:#efa4b8}.bg-light-yellow{background-color:#f3dd70}.bg-light-red{background-color:#ffd3c0}.hover-black:hover{color:#000}.hover-near-black:hover{color:#111}.hover-dark-gray:hover{color:#333}.hover-mid-gray:hover{color:#555}.hover-gray:hover{color:#777}.hover-silver:hover{color:#999}.hover-light-silver:hover{color:#aaa}.hover-moon-gray:hover{color:#ccc}.hover-light-gray:hover{color:#eee}.hover-near-white:hover{color:#f4f4f4}.hover-white:hover{color:#fff}.hover-bg-black:hover{background-color:#000}.hover-bg-near-black:hover{background-color:#111}.hover-bg-dark-gray:hover{background-color:#333}.hover-bg-mid-gray:hover{background-color:#555}.hover-bg-gray:hover{background-color:#777}.hover-bg-silver:hover{background-color:#999}.hover-bg-light-silver:hover{background-color:#aaa}.hover-bg-moon-gray:hover{background-color:#ccc}.hover-bg-light-gray:hover{background-color:#eee}.hover-bg-near-white:hover{background-color:#f4f4f4}.hover-bg-white:hover{background-color:#fff}.hover-bg-transparent:hover{background-color:transparent}.hover-bg-dark-red:hover{background-color:#f00008}.hover-bg-red:hover{background-color:#ff3223}.hover-bg-orange:hover{background-color:#f3a801}.hover-bg-gold:hover{background-color:#f2c800}.hover-bg-yellow:hover{background-color:#ffde37}.hover-bg-purple:hover{background-color:#7d5da9}.hover-bg-light-purple:hover{background-color:#8d4f92}.hover-bg-hot-pink:hover{background-color:#d62288}.hover-bg-dark-pink:hover{background-color:#c64774}.hover-bg-pink:hover{background-color:#f49cc8}.hover-bg-dark-green:hover{background-color:#006c71}.hover-bg-green:hover{background-color:#41d69f}.hover-bg-navy:hover{background-color:#001b44}.hover-bg-dark-blue:hover{background-color:#00449e}.hover-bg-blue:hover{background-color:#357edd}.hover-bg-light-blue:hover{background-color:#96ccff}.hover-bg-lightest-blue:hover{background-color:#cdecff}.hover-bg-washed-blue:hover{background-color:#f6fffe}.hover-bg-washed-green:hover{background-color:#e8fdf5}.hover-bg-washed-yellow:hover{background-color:#fff8d5}.hover-bg-light-pink:hover{background-color:#efa4b8}.hover-bg-light-yellow:hover{background-color:#f3dd70}.hover-bg-light-red:hover{background-color:#ffd3c0}.pa0{padding:0}.pa1{padding:.25rem}.pa2{padding:.5rem}.pa3{padding:1rem}.pa4{padding:2rem}.pa5{padding:4rem}.pa6{padding:8rem}.pa7{padding:16rem}.pl0{padding-left:0}.pl1{padding-left:.25rem}.pl2{padding-left:.5rem}.pl3{padding-left:1rem}.pl4{padding-left:2rem}.pl5{padding-left:4rem}.pl6{padding-left:8rem}.pl7{padding-left:16rem}.pr0{padding-right:0}.pr1{padding-right:.25rem}.pr2{padding-right:.5rem}.pr3{padding-right:1rem}.pr4{padding-right:2rem}.pr5{padding-right:4rem}.pr6{padding-right:8rem}.pr7{padding-right:16rem}.pb0{padding-bottom:0}.pb1{padding-bottom:.25rem}.pb2{padding-bottom:.5rem}.pb3{padding-bottom:1rem}.pb4{padding-bottom:2rem}.pb5{padding-bottom:4rem}.pb6{padding-bottom:8rem}.pb7{padding-bottom:16rem}.pt0{padding-top:0}.pt1{padding-top:.25rem}.pt2{padding-top:.5rem}.pt3{padding-top:1rem}.pt4{padding-top:2rem}.pt5{padding-top:4rem}.pt6{padding-top:8rem}.pt7{padding-top:16rem}.pv0{padding-top:0;padding-bottom:0}.pv1{padding-top:.25rem;padding-bottom:.25rem}.pv2{padding-top:.5rem;padding-bottom:.5rem}.pv3{padding-top:1rem;padding-bottom:1rem}.pv4{padding-top:2rem;padding-bottom:2rem}.pv5{padding-top:4rem;padding-bottom:4rem}.pv6{padding-top:8rem;padding-bottom:8rem}.pv7{padding-top:16rem;padding-bottom:16rem}.ph0{padding-left:0;padding-right:0}.ph1{padding-left:.25rem;padding-right:.25rem}.ph2{padding-left:.5rem;padding-right:.5rem}.ph3{padding-left:1rem;padding-right:1rem}.ph4{padding-left:2rem;padding-right:2rem}.ph5{padding-left:4rem;padding-right:4rem}.ph6{padding-left:8rem;padding-right:8rem}.ph7{padding-left:16rem;padding-right:16rem}.ma0{margin:0}.ma1{margin:.25rem}.ma2{margin:.5rem}.ma3{margin:1rem}.ma4{margin:2rem}.ma5{margin:4rem}.ma6{margin:8rem}.ma7{margin:16rem}.ml0{margin-left:0}.ml1{margin-left:.25rem}.ml2{margin-left:.5rem}.ml3{margin-left:1rem}.ml4{margin-left:2rem}.ml5{margin-left:4rem}.ml6{margin-left:8rem}.ml7{margin-left:16rem}.mr0{margin-right:0}.mr1{margin-right:.25rem}.mr2{margin-right:.5rem}.mr3{margin-right:1rem}.mr4{margin-right:2rem}.mr5{margin-right:4rem}.mr6{margin-right:8rem}.mr7{margin-right:16rem}.mb0{margin-bottom:0}.mb1{margin-bottom:.25rem}.mb2{margin-bottom:.5rem}.mb3{margin-bottom:1rem}.mb4{margin-bottom:2rem}.mb5{margin-bottom:4rem}.mb6{margin-bottom:8rem}.mb7{margin-bottom:16rem}.mt0{margin-top:0}.mt1{margin-top:.25rem}.mt2{margin-top:.5rem}.mt3{margin-top:1rem}.mt4{margin-top:2rem}.mt5{margin-top:4rem}.mt6{margin-top:8rem}.mt7{margin-top:16rem}.mv0{margin-top:0;margin-bottom:0}.mv1{margin-top:.25rem;margin-bottom:.25rem}.mv2{margin-top:.5rem;margin-bottom:.5rem}.mv3{margin-top:1rem;margin-bottom:1rem}.mv4{margin-top:2rem;margin-bottom:2rem}.mv5{margin-top:4rem;margin-bottom:4rem}.mv6{margin-top:8rem;margin-bottom:8rem}.mv7{margin-top:16rem;margin-bottom:16rem}.mh0{margin-left:0;margin-right:0}.mh1{margin-left:.25rem;margin-right:.25rem}.mh2{margin-left:.5rem;margin-right:.5rem}.mh3{margin-left:1rem;margin-right:1rem}.mh4{margin-left:2rem;margin-right:2rem}.mh5{margin-left:4rem;margin-right:4rem}.mh6{margin-left:8rem;margin-right:8rem}.mh7{margin-left:16rem;margin-right:16rem}.collapse{border-collapse:collapse;border-spacing:0}.striped--moon-gray:nth-child(odd){background-color:#aaa;background-color:#ccc}.striped--light-gray:nth-child(odd){background-color:#eee}.striped--near-white:nth-child(odd){background-color:#f4f4f4}.strike{text-decoration:line-through}.underline{text-decoration:underline}.no-underline{text-decoration:none}.tl{text-align:left}.tr{text-align:right}.tc{text-align:center}.ttc{text-transform:capitalize}.ttl{text-transform:lowercase}.ttu{text-transform:uppercase}.ttn{text-transform:none}.f-6,.f-headline{font-size:6rem}.f-5,.f-subheadline{font-size:5rem}.f1{font-size:3rem}.f2{font-size:2.25rem}.f3{font-size:1.5rem}.f4{font-size:1.25rem}.f5{font-size:1rem}.f6{font-size:.875rem}.measure{max-width:30em}.measure-wide{max-width:34em}.measure-narrow{max-width:20em}.indent{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps{font-variant:small-caps}.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aspect-ratio{height:0;position:relative}.aspect-ratio--16x9{padding-bottom:56.25%}.aspect-ratio--4x3{padding-bottom:75%}.aspect-ratio--8x5{padding-bottom:62.5%}.aspect-ratio--object{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:1}.overflow-container{overflow-y:scroll}.center{margin-right:auto;margin-left:auto}.clip{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal{white-space:normal}.nowrap{white-space:nowrap}.pre{white-space:pre}.v-base{vertical-align:baseline}.v-mid{vertical-align:middle}.v-top{vertical-align:top}.v-btm{vertical-align:bottom}.dim{opacity:1}.dim,.dim:focus,.dim:hover{transition:opacity .15s ease-in}.dim:focus,.dim:hover{opacity:.5}.dim:active{opacity:.8;transition:opacity .15s ease-out}.hide-child .child{opacity:0;transition:opacity .15s ease-in}.hide-child:active .child,.hide-child:focus .child,.hide-child:hover .child{opacity:1;transition:opacity .15s ease-in}.underline-hover:focus,.underline-hover:hover{text-decoration:underline}.grow{transition:transform .2s}.grow:hover{transform:scale(1.05)}.grow-large{transition:transform .2s}.grow-large:hover{transform:scale(1.2)}.pointer:hover{cursor:pointer}.debug *{outline:1px solid gold}@media screen and (min-width:30em){.cover-ns{background-size:cover}.contain-ns{background-size:contain}.ba-ns{border-style:solid;border-width:1px}.bt-ns{border-top-style:solid;border-top-width:1px}.br-ns{border-right-style:solid;border-right-width:1px}.bb-ns{border-bottom-style:solid;border-bottom-width:1px}.bl-ns{border-left-style:solid;border-left-width:1px}.bn-ns{border-style:none;border-width:0}.br0-ns{border-radius:0}.br1-ns{border-radius:.125rem}.br2-ns{border-radius:.25rem}.br3-ns{border-radius:.5rem}.br4-ns{border-radius:1rem}.br-100-ns{border-radius:100%}.br--bottom-ns{border-top-left-radius:0;border-top-right-radius:0}.br--top-ns{border-bottom-right-radius:0}.br--right-ns,.br--top-ns{border-bottom-left-radius:0}.br--right-ns{border-top-left-radius:0}.br--left-ns{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted-ns{border-style:dotted}.b--dashed-ns{border-style:dashed}.b--solid-ns{border-style:solid}.b--none-ns{border-style:none}.bw0-ns{border-width:0}.bw1-ns{border-width:.125rem}.bw2-ns{border-width:.25rem}.bw3-ns{border-width:.5rem}.bw4-ns{border-width:1rem}.bw5-ns{border-width:2rem}.bt-0-ns{border-top-width:0}.br-0-ns{border-right-width:0}.bb-0-ns{border-bottom-width:0}.bl-0-ns{border-left-width:0}.shadow-1-ns{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-ns{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-ns{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-ns{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-ns{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.top-0-ns{top:0}.left-0-ns{left:0}.right-0-ns{right:0}.bottom-0-ns{bottom:0}.top-1-ns{top:1rem}.left-1-ns{left:1rem}.right-1-ns{right:1rem}.bottom-1-ns{bottom:1rem}.top-2-ns{top:2rem}.left-2-ns{left:2rem}.right-2-ns{right:2rem}.bottom-2-ns{bottom:2rem}.top--1-ns{top:-1rem}.right--1-ns{right:-1rem}.bottom--1-ns{bottom:-1rem}.left--1-ns{left:-1rem}.top--2-ns{top:-2rem}.right--2-ns{right:-2rem}.bottom--2-ns{bottom:-2rem}.left--2-ns{left:-2rem}.absolute--fill-ns{top:0;right:0;bottom:0;left:0}.cl-ns{clear:left}.cr-ns{clear:right}.cb-ns{clear:both}.cn-ns{clear:none}.dn-ns{display:none}.di-ns{display:inline}.db-ns{display:block}.dib-ns{display:inline-block}.dit-ns{display:inline-table}.dt-ns{display:table}.dtc-ns{display:table-cell}.dt-row-ns{display:table-row}.dt-row-group-ns{display:table-row-group}.dt-column-ns{display:table-column}.dt-column-group-ns{display:table-column-group}.dt--fixed-ns{table-layout:fixed;width:100%}.flex-ns{display:flex}.flex-auto-ns{flex:1 1 auto;min-width:0;min-height:0}.flex-none-ns{flex:none}.flex-column-ns{flex-direction:column}.flex-wrap-ns{flex-wrap:wrap}.items-start-ns{align-items:flex-start}.items-end-ns{align-items:flex-end}.items-center-ns{align-items:center}.items-baseline-ns{align-items:baseline}.items-stretch-ns{align-items:stretch}.self-start-ns{align-self:flex-start}.self-end-ns{align-self:flex-end}.self-center-ns{align-self:center}.self-baseline-ns{align-self:baseline}.self-stretch-ns{align-self:stretch}.justify-start-ns{justify-content:flex-start}.justify-end-ns{justify-content:flex-end}.justify-center-ns{justify-content:center}.justify-between-ns{justify-content:space-between}.justify-around-ns{justify-content:space-around}.content-start-ns{align-content:flex-start}.content-end-ns{align-content:flex-end}.content-center-ns{align-content:center}.content-between-ns{align-content:space-between}.content-around-ns{align-content:space-around}.content-stretch-ns{align-content:stretch}.order-0-ns{order:0}.order-1-ns{order:1}.order-2-ns{order:2}.order-3-ns{order:3}.order-4-ns{order:4}.order-5-ns{order:5}.order-6-ns{order:6}.order-7-ns{order:7}.order-8-ns{order:8}.order-last-ns{order:99999}.fl-ns{float:left}.fl-ns,.fr-ns{display:inline}.fr-ns{float:right}.fn-ns{float:none}.i-ns{font-style:italic}.fs-normal-ns{font-style:normal}.normal-ns{font-weight:400}.b-ns{font-weight:700}.fw1-ns{font-weight:100}.fw2-ns{font-weight:200}.fw3-ns{font-weight:300}.fw4-ns{font-weight:400}.fw5-ns{font-weight:500}.fw6-ns{font-weight:600}.fw7-ns{font-weight:700}.fw8-ns{font-weight:800}.fw9-ns{font-weight:900}.h1-ns{height:1rem}.h2-ns{height:2rem}.h3-ns{height:4rem}.h4-ns{height:8rem}.h5-ns{height:16rem}.h-25-ns{height:25%}.h-50-ns{height:50%}.h-75-ns{height:75%}.h-100-ns{height:100%}.h-auto-ns{height:auto}.h-inherit-ns{height:inherit}.tracked-ns{letter-spacing:.16em}.tracked-tight-ns{letter-spacing:-.05em}.tracked-mega-ns{letter-spacing:.32em}.lh-solid-ns{line-height:1}.lh-title-ns{line-height:1.3}.lh-copy-ns{line-height:1.6}.mw-100-ns{max-width:100%}.mw1-ns{max-width:1rem}.mw2-ns{max-width:2rem}.mw3-ns{max-width:4rem}.mw4-ns{max-width:8rem}.mw5-ns{max-width:16rem}.mw6-ns{max-width:32rem}.mw7-ns{max-width:48rem}.mw8-ns{max-width:64rem}.mw9-ns{max-width:96rem}.mw-none-ns{max-width:none}.w1-ns{width:1rem}.w2-ns{width:2rem}.w3-ns{width:4rem}.w4-ns{width:8rem}.w5-ns{width:16rem}.w-10-ns{width:10%}.w-20-ns{width:20%}.w-25-ns{width:25%}.w-33-ns{width:33%}.w-34-ns{width:34%}.w-40-ns{width:40%}.w-50-ns{width:50%}.w-60-ns{width:60%}.w-75-ns{width:75%}.w-80-ns{width:80%}.w-100-ns{width:100%}.w-auto-ns{width:auto}.overflow-visible-ns{overflow:visible}.overflow-hidden-ns{overflow:hidden}.overflow-scroll-ns{overflow:scroll}.overflow-auto-ns{overflow:auto}.overflow-x-visible-ns{overflow-x:visible}.overflow-x-hidden-ns{overflow-x:hidden}.overflow-x-scroll-ns{overflow-x:scroll}.overflow-x-auto-ns{overflow-x:auto}.overflow-y-visible-ns{overflow-y:visible}.overflow-y-hidden-ns{overflow-y:hidden}.overflow-y-scroll-ns{overflow-y:scroll}.overflow-y-auto-ns{overflow-y:auto}.static-ns{position:static}.relative-ns{position:relative}.absolute-ns{position:absolute}.fixed-ns{position:fixed}.pa0-ns{padding:0}.pa1-ns{padding:.25rem}.pa2-ns{padding:.5rem}.pa3-ns{padding:1rem}.pa4-ns{padding:2rem}.pa5-ns{padding:4rem}.pa6-ns{padding:8rem}.pa7-ns{padding:16rem}.pl0-ns{padding-left:0}.pl1-ns{padding-left:.25rem}.pl2-ns{padding-left:.5rem}.pl3-ns{padding-left:1rem}.pl4-ns{padding-left:2rem}.pl5-ns{padding-left:4rem}.pl6-ns{padding-left:8rem}.pl7-ns{padding-left:16rem}.pr0-ns{padding-right:0}.pr1-ns{padding-right:.25rem}.pr2-ns{padding-right:.5rem}.pr3-ns{padding-right:1rem}.pr4-ns{padding-right:2rem}.pr5-ns{padding-right:4rem}.pr6-ns{padding-right:8rem}.pr7-ns{padding-right:16rem}.pb0-ns{padding-bottom:0}.pb1-ns{padding-bottom:.25rem}.pb2-ns{padding-bottom:.5rem}.pb3-ns{padding-bottom:1rem}.pb4-ns{padding-bottom:2rem}.pb5-ns{padding-bottom:4rem}.pb6-ns{padding-bottom:8rem}.pb7-ns{padding-bottom:16rem}.pt0-ns{padding-top:0}.pt1-ns{padding-top:.25rem}.pt2-ns{padding-top:.5rem}.pt3-ns{padding-top:1rem}.pt4-ns{padding-top:2rem}.pt5-ns{padding-top:4rem}.pt6-ns{padding-top:8rem}.pt7-ns{padding-top:16rem}.pv0-ns{padding-top:0;padding-bottom:0}.pv1-ns{padding-top:.25rem;padding-bottom:.25rem}.pv2-ns{padding-top:.5rem;padding-bottom:.5rem}.pv3-ns{padding-top:1rem;padding-bottom:1rem}.pv4-ns{padding-top:2rem;padding-bottom:2rem}.pv5-ns{padding-top:4rem;padding-bottom:4rem}.pv6-ns{padding-top:8rem;padding-bottom:8rem}.pv7-ns{padding-top:16rem;padding-bottom:16rem}.ph0-ns{padding-left:0;padding-right:0}.ph1-ns{padding-left:.25rem;padding-right:.25rem}.ph2-ns{padding-left:.5rem;padding-right:.5rem}.ph3-ns{padding-left:1rem;padding-right:1rem}.ph4-ns{padding-left:2rem;padding-right:2rem}.ph5-ns{padding-left:4rem;padding-right:4rem}.ph6-ns{padding-left:8rem;padding-right:8rem}.ph7-ns{padding-left:16rem;padding-right:16rem}.ma0-ns{margin:0}.ma1-ns{margin:.25rem}.ma2-ns{margin:.5rem}.ma3-ns{margin:1rem}.ma4-ns{margin:2rem}.ma5-ns{margin:4rem}.ma6-ns{margin:8rem}.ma7-ns{margin:16rem}.ml0-ns{margin-left:0}.ml1-ns{margin-left:.25rem}.ml2-ns{margin-left:.5rem}.ml3-ns{margin-left:1rem}.ml4-ns{margin-left:2rem}.ml5-ns{margin-left:4rem}.ml6-ns{margin-left:8rem}.ml7-ns{margin-left:16rem}.mr0-ns{margin-right:0}.mr1-ns{margin-right:.25rem}.mr2-ns{margin-right:.5rem}.mr3-ns{margin-right:1rem}.mr4-ns{margin-right:2rem}.mr5-ns{margin-right:4rem}.mr6-ns{margin-right:8rem}.mr7-ns{margin-right:16rem}.mb0-ns{margin-bottom:0}.mb1-ns{margin-bottom:.25rem}.mb2-ns{margin-bottom:.5rem}.mb3-ns{margin-bottom:1rem}.mb4-ns{margin-bottom:2rem}.mb5-ns{margin-bottom:4rem}.mb6-ns{margin-bottom:8rem}.mb7-ns{margin-bottom:16rem}.mt0-ns{margin-top:0}.mt1-ns{margin-top:.25rem}.mt2-ns{margin-top:.5rem}.mt3-ns{margin-top:1rem}.mt4-ns{margin-top:2rem}.mt5-ns{margin-top:4rem}.mt6-ns{margin-top:8rem}.mt7-ns{margin-top:16rem}.mv0-ns{margin-top:0;margin-bottom:0}.mv1-ns{margin-top:.25rem;margin-bottom:.25rem}.mv2-ns{margin-top:.5rem;margin-bottom:.5rem}.mv3-ns{margin-top:1rem;margin-bottom:1rem}.mv4-ns{margin-top:2rem;margin-bottom:2rem}.mv5-ns{margin-top:4rem;margin-bottom:4rem}.mv6-ns{margin-top:8rem;margin-bottom:8rem}.mv7-ns{margin-top:16rem;margin-bottom:16rem}.mh0-ns{margin-left:0;margin-right:0}.mh1-ns{margin-left:.25rem;margin-right:.25rem}.mh2-ns{margin-left:.5rem;margin-right:.5rem}.mh3-ns{margin-left:1rem;margin-right:1rem}.mh4-ns{margin-left:2rem;margin-right:2rem}.mh5-ns{margin-left:4rem;margin-right:4rem}.mh6-ns{margin-left:8rem;margin-right:8rem}.mh7-ns{margin-left:16rem;margin-right:16rem}.strike-ns{text-decoration:line-through}.underline-ns{text-decoration:underline}.no-underline-ns{text-decoration:none}.tl-ns{text-align:left}.tr-ns{text-align:right}.tc-ns{text-align:center}.ttc-ns{text-transform:capitalize}.ttl-ns{text-transform:lowercase}.ttu-ns{text-transform:uppercase}.ttn-ns{text-transform:none}.f-6-ns,.f-headline-ns{font-size:6rem}.f-5-ns,.f-subheadline-ns{font-size:5rem}.f1-ns{font-size:3rem}.f2-ns{font-size:2.25rem}.f3-ns{font-size:1.5rem}.f4-ns{font-size:1.25rem}.f5-ns{font-size:1rem}.f6-ns{font-size:.875rem}.measure-ns{max-width:30em}.measure-wide-ns{max-width:34em}.measure-narrow-ns{max-width:20em}.indent-ns{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-ns{font-variant:small-caps}.truncate-ns{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.clip-ns{position:fixed!important;position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal-ns{white-space:normal}.nowrap-ns{white-space:nowrap}.pre-ns{white-space:pre}.v-base-ns{vertical-align:baseline}.v-mid-ns{vertical-align:middle}.v-top-ns{vertical-align:top}.v-btm-ns{vertical-align:bottom}}@media screen and (min-width:30em) and (max-width:60em){.cover-m{background-size:cover}.contain-m{background-size:contain}.ba-m{border-style:solid;border-width:1px}.bt-m{border-top-style:solid;border-top-width:1px}.br-m{border-right-style:solid;border-right-width:1px}.bb-m{border-bottom-style:solid;border-bottom-width:1px}.bl-m{border-left-style:solid;border-left-width:1px}.bn-m{border-style:none;border-width:0}.br0-m{border-radius:0}.br1-m{border-radius:.125rem}.br2-m{border-radius:.25rem}.br3-m{border-radius:.5rem}.br4-m{border-radius:1rem}.br-100-m{border-radius:100%}.br--bottom-m{border-top-left-radius:0;border-top-right-radius:0}.br--top-m{border-bottom-right-radius:0}.br--right-m,.br--top-m{border-bottom-left-radius:0}.br--right-m{border-top-left-radius:0}.br--left-m{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted-m{border-style:dotted}.b--dashed-m{border-style:dashed}.b--solid-m{border-style:solid}.b--none-m{border-style:none}.bw0-m{border-width:0}.bw1-m{border-width:.125rem}.bw2-m{border-width:.25rem}.bw3-m{border-width:.5rem}.bw4-m{border-width:1rem}.bw5-m{border-width:2rem}.bt-0-m{border-top-width:0}.br-0-m{border-right-width:0}.bb-0-m{border-bottom-width:0}.bl-0-m{border-left-width:0}.shadow-1-m{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-m{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-m{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-m{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-m{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.top-0-m{top:0}.left-0-m{left:0}.right-0-m{right:0}.bottom-0-m{bottom:0}.top-1-m{top:1rem}.left-1-m{left:1rem}.right-1-m{right:1rem}.bottom-1-m{bottom:1rem}.top-2-m{top:2rem}.left-2-m{left:2rem}.right-2-m{right:2rem}.bottom-2-m{bottom:2rem}.top--1-m{top:-1rem}.right--1-m{right:-1rem}.bottom--1-m{bottom:-1rem}.left--1-m{left:-1rem}.top--2-m{top:-2rem}.right--2-m{right:-2rem}.bottom--2-m{bottom:-2rem}.left--2-m{left:-2rem}.absolute--fill-m{top:0;right:0;bottom:0;left:0}.cl-m{clear:left}.cr-m{clear:right}.cb-m{clear:both}.cn-m{clear:none}.dn-m{display:none}.di-m{display:inline}.db-m{display:block}.dib-m{display:inline-block}.dit-m{display:inline-table}.dt-m{display:table}.dtc-m{display:table-cell}.dt-row-m{display:table-row}.dt-row-group-m{display:table-row-group}.dt-column-m{display:table-column}.dt-column-group-m{display:table-column-group}.dt--fixed-m{table-layout:fixed;width:100%}.flex-m{display:flex}.flex-auto-m{flex:1 1 auto;min-width:0;min-height:0}.flex-none-m{flex:none}.flex-column-m{flex-direction:column}.flex-wrap-m{flex-wrap:wrap}.items-start-m{align-items:flex-start}.items-end-m{align-items:flex-end}.items-center-m{align-items:center}.items-baseline-m{align-items:baseline}.items-stretch-m{align-items:stretch}.self-start-m{align-self:flex-start}.self-end-m{align-self:flex-end}.self-center-m{align-self:center}.self-baseline-m{align-self:baseline}.self-stretch-m{align-self:stretch}.justify-start-m{justify-content:flex-start}.justify-end-m{justify-content:flex-end}.justify-center-m{justify-content:center}.justify-between-m{justify-content:space-between}.justify-around-m{justify-content:space-around}.content-start-m{align-content:flex-start}.content-end-m{align-content:flex-end}.content-center-m{align-content:center}.content-between-m{align-content:space-between}.content-around-m{align-content:space-around}.content-stretch-m{align-content:stretch}.order-0-m{order:0}.order-1-m{order:1}.order-2-m{order:2}.order-3-m{order:3}.order-4-m{order:4}.order-5-m{order:5}.order-6-m{order:6}.order-7-m{order:7}.order-8-m{order:8}.order-last-m{order:99999}.fl-m{float:left}.fl-m,.fr-m{display:inline}.fr-m{float:right}.fn-m{float:none}.i-m{font-style:italic}.fs-normal-m{font-style:normal}.normal-m{font-weight:400}.b-m{font-weight:700}.fw1-m{font-weight:100}.fw2-m{font-weight:200}.fw3-m{font-weight:300}.fw4-m{font-weight:400}.fw5-m{font-weight:500}.fw6-m{font-weight:600}.fw7-m{font-weight:700}.fw8-m{font-weight:800}.fw9-m{font-weight:900}.h1-m{height:1rem}.h2-m{height:2rem}.h3-m{height:4rem}.h4-m{height:8rem}.h5-m{height:16rem}.h-25-m{height:25%}.h-50-m{height:50%}.h-75-m{height:75%}.h-100-m{height:100%}.h-auto-m{height:auto}.h-inherit-m{height:inherit}.tracked-m{letter-spacing:.16em}.tracked-tight-m{letter-spacing:-.05em}.tracked-mega-m{letter-spacing:.32em}.lh-solid-m{line-height:1}.lh-title-m{line-height:1.3}.lh-copy-m{line-height:1.6}.mw-100-m{max-width:100%}.mw1-m{max-width:1rem}.mw2-m{max-width:2rem}.mw3-m{max-width:4rem}.mw4-m{max-width:8rem}.mw5-m{max-width:16rem}.mw6-m{max-width:32rem}.mw7-m{max-width:48rem}.mw8-m{max-width:64rem}.mw9-m{max-width:96rem}.mw-none-m{max-width:none}.w1-m{width:1rem}.w2-m{width:2rem}.w3-m{width:4rem}.w4-m{width:8rem}.w5-m{width:16rem}.w-10-m{width:10%}.w-20-m{width:20%}.w-25-m{width:25%}.w-33-m{width:33%}.w-34-m{width:34%}.w-40-m{width:40%}.w-50-m{width:50%}.w-60-m{width:60%}.w-75-m{width:75%}.w-80-m{width:80%}.w-100-m{width:100%}.w-auto-m{width:auto}.overflow-visible-m{overflow:visible}.overflow-hidden-m{overflow:hidden}.overflow-scroll-m{overflow:scroll}.overflow-auto-m{overflow:auto}.overflow-x-visible-m{overflow-x:visible}.overflow-x-hidden-m{overflow-x:hidden}.overflow-x-scroll-m{overflow-x:scroll}.overflow-x-auto-m{overflow-x:auto}.overflow-y-visible-m{overflow-y:visible}.overflow-y-hidden-m{overflow-y:hidden}.overflow-y-scroll-m{overflow-y:scroll}.overflow-y-auto-m{overflow-y:auto}.static-m{position:static}.relative-m{position:relative}.absolute-m{position:absolute}.fixed-m{position:fixed}.pa0-m{padding:0}.pa1-m{padding:.25rem}.pa2-m{padding:.5rem}.pa3-m{padding:1rem}.pa4-m{padding:2rem}.pa5-m{padding:4rem}.pa6-m{padding:8rem}.pa7-m{padding:16rem}.pl0-m{padding-left:0}.pl1-m{padding-left:.25rem}.pl2-m{padding-left:.5rem}.pl3-m{padding-left:1rem}.pl4-m{padding-left:2rem}.pl5-m{padding-left:4rem}.pl6-m{padding-left:8rem}.pl7-m{padding-left:16rem}.pr0-m{padding-right:0}.pr1-m{padding-right:.25rem}.pr2-m{padding-right:.5rem}.pr3-m{padding-right:1rem}.pr4-m{padding-right:2rem}.pr5-m{padding-right:4rem}.pr6-m{padding-right:8rem}.pr7-m{padding-right:16rem}.pb0-m{padding-bottom:0}.pb1-m{padding-bottom:.25rem}.pb2-m{padding-bottom:.5rem}.pb3-m{padding-bottom:1rem}.pb4-m{padding-bottom:2rem}.pb5-m{padding-bottom:4rem}.pb6-m{padding-bottom:8rem}.pb7-m{padding-bottom:16rem}.pt0-m{padding-top:0}.pt1-m{padding-top:.25rem}.pt2-m{padding-top:.5rem}.pt3-m{padding-top:1rem}.pt4-m{padding-top:2rem}.pt5-m{padding-top:4rem}.pt6-m{padding-top:8rem}.pt7-m{padding-top:16rem}.pv0-m{padding-top:0;padding-bottom:0}.pv1-m{padding-top:.25rem;padding-bottom:.25rem}.pv2-m{padding-top:.5rem;padding-bottom:.5rem}.pv3-m{padding-top:1rem;padding-bottom:1rem}.pv4-m{padding-top:2rem;padding-bottom:2rem}.pv5-m{padding-top:4rem;padding-bottom:4rem}.pv6-m{padding-top:8rem;padding-bottom:8rem}.pv7-m{padding-top:16rem;padding-bottom:16rem}.ph0-m{padding-left:0;padding-right:0}.ph1-m{padding-left:.25rem;padding-right:.25rem}.ph2-m{padding-left:.5rem;padding-right:.5rem}.ph3-m{padding-left:1rem;padding-right:1rem}.ph4-m{padding-left:2rem;padding-right:2rem}.ph5-m{padding-left:4rem;padding-right:4rem}.ph6-m{padding-left:8rem;padding-right:8rem}.ph7-m{padding-left:16rem;padding-right:16rem}.ma0-m{margin:0}.ma1-m{margin:.25rem}.ma2-m{margin:.5rem}.ma3-m{margin:1rem}.ma4-m{margin:2rem}.ma5-m{margin:4rem}.ma6-m{margin:8rem}.ma7-m{margin:16rem}.ml0-m{margin-left:0}.ml1-m{margin-left:.25rem}.ml2-m{margin-left:.5rem}.ml3-m{margin-left:1rem}.ml4-m{margin-left:2rem}.ml5-m{margin-left:4rem}.ml6-m{margin-left:8rem}.ml7-m{margin-left:16rem}.mr0-m{margin-right:0}.mr1-m{margin-right:.25rem}.mr2-m{margin-right:.5rem}.mr3-m{margin-right:1rem}.mr4-m{margin-right:2rem}.mr5-m{margin-right:4rem}.mr6-m{margin-right:8rem}.mr7-m{margin-right:16rem}.mb0-m{margin-bottom:0}.mb1-m{margin-bottom:.25rem}.mb2-m{margin-bottom:.5rem}.mb3-m{margin-bottom:1rem}.mb4-m{margin-bottom:2rem}.mb5-m{margin-bottom:4rem}.mb6-m{margin-bottom:8rem}.mb7-m{margin-bottom:16rem}.mt0-m{margin-top:0}.mt1-m{margin-top:.25rem}.mt2-m{margin-top:.5rem}.mt3-m{margin-top:1rem}.mt4-m{margin-top:2rem}.mt5-m{margin-top:4rem}.mt6-m{margin-top:8rem}.mt7-m{margin-top:16rem}.mv0-m{margin-top:0;margin-bottom:0}.mv1-m{margin-top:.25rem;margin-bottom:.25rem}.mv2-m{margin-top:.5rem;margin-bottom:.5rem}.mv3-m{margin-top:1rem;margin-bottom:1rem}.mv4-m{margin-top:2rem;margin-bottom:2rem}.mv5-m{margin-top:4rem;margin-bottom:4rem}.mv6-m{margin-top:8rem;margin-bottom:8rem}.mv7-m{margin-top:16rem;margin-bottom:16rem}.mh0-m{margin-left:0;margin-right:0}.mh1-m{margin-left:.25rem;margin-right:.25rem}.mh2-m{margin-left:.5rem;margin-right:.5rem}.mh3-m{margin-left:1rem;margin-right:1rem}.mh4-m{margin-left:2rem;margin-right:2rem}.mh5-m{margin-left:4rem;margin-right:4rem}.mh6-m{margin-left:8rem;margin-right:8rem}.mh7-m{margin-left:16rem;margin-right:16rem}.strike-m{text-decoration:line-through}.underline-m{text-decoration:underline}.no-underline-m{text-decoration:none}.tl-m{text-align:left}.tr-m{text-align:right}.tc-m{text-align:center}.ttc-m{text-transform:capitalize}.ttl-m{text-transform:lowercase}.ttu-m{text-transform:uppercase}.ttn-m{text-transform:none}.f-6-m,.f-headline-m{font-size:6rem}.f-5-m,.f-subheadline-m{font-size:5rem}.f1-m{font-size:3rem}.f2-m{font-size:2.25rem}.f3-m{font-size:1.5rem}.f4-m{font-size:1.25rem}.f5-m{font-size:1rem}.f6-m{font-size:.875rem}.measure-m{max-width:30em}.measure-wide-m{max-width:34em}.measure-narrow-m{max-width:20em}.indent-m{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-m{font-variant:small-caps}.truncate-m{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.clip-m{position:fixed!important;position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal-m{white-space:normal}.nowrap-m{white-space:nowrap}.pre-m{white-space:pre}.v-base-m{vertical-align:baseline}.v-mid-m{vertical-align:middle}.v-top-m{vertical-align:top}.v-btm-m{vertical-align:bottom}}@media screen and (min-width:60em){.cover-l{background-size:cover}.contain-l{background-size:contain}.ba-l{border-style:solid;border-width:1px}.bt-l{border-top-style:solid;border-top-width:1px}.br-l{border-right-style:solid;border-right-width:1px}.bb-l{border-bottom-style:solid;border-bottom-width:1px}.bl-l{border-left-style:solid;border-left-width:1px}.bn-l{border-style:none;border-width:0}.br0-l{border-radius:0}.br1-l{border-radius:.125rem}.br2-l{border-radius:.25rem}.br3-l{border-radius:.5rem}.br4-l{border-radius:1rem}.br-100-l{border-radius:100%}.br--bottom-l{border-radius-top-left:0;border-radius-top-right:0}.br--top-l{border-bottom-right-radius:0}.br--right-l,.br--top-l{border-bottom-left-radius:0}.br--right-l{border-top-left-radius:0}.br--left-l{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted-l{border-style:dotted}.b--dashed-l{border-style:dashed}.b--solid-l{border-style:solid}.b--none-l{border-style:none}.bw0-l{border-width:0}.bw1-l{border-width:.125rem}.bw2-l{border-width:.25rem}.bw3-l{border-width:.5rem}.bw4-l{border-width:1rem}.bw5-l{border-width:2rem}.bt-0-l{border-top-width:0}.br-0-l{border-right-width:0}.bb-0-l{border-bottom-width:0}.bl-0-l{border-left-width:0}.shadow-1-l{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-l{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-l{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-l{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-l{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.top-0-l{top:0}.left-0-l{left:0}.right-0-l{right:0}.bottom-0-l{bottom:0}.top-1-l{top:1rem}.left-1-l{left:1rem}.right-1-l{right:1rem}.bottom-1-l{bottom:1rem}.top-2-l{top:2rem}.left-2-l{left:2rem}.right-2-l{right:2rem}.bottom-2-l{bottom:2rem}.top--1-l{top:-1rem}.right--1-l{right:-1rem}.bottom--1-l{bottom:-1rem}.left--1-l{left:-1rem}.top--2-l{top:-2rem}.right--2-l{right:-2rem}.bottom--2-l{bottom:-2rem}.left--2-l{left:-2rem}.absolute--fill-l{top:0;right:0;bottom:0;left:0}.cl-l{clear:left}.cr-l{clear:right}.cb-l{clear:both}.cn-l{clear:none}.dn-l{display:none}.di-l{display:inline}.db-l{display:block}.dib-l{display:inline-block}.dit-l{display:inline-table}.dt-l{display:table}.dtc-l{display:table-cell}.dt-row-l{display:table-row}.dt-row-group-l{display:table-row-group}.dt-column-l{display:table-column}.dt-column-group-l{display:table-column-group}.dt--fixed-l{table-layout:fixed;width:100%}.flex-l{display:flex}.flex-auto-l{flex:1 1 auto;min-width:0;min-height:0}.flex-none-l{flex:none}.flex-column-l{flex-direction:column}.flex-wrap-l{flex-wrap:wrap}.items-start-l{align-items:flex-start}.items-end-l{align-items:flex-end}.items-center-l{align-items:center}.items-baseline-l{align-items:baseline}.items-stretch-l{align-items:stretch}.self-start-l{align-self:flex-start}.self-end-l{align-self:flex-end}.self-center-l{align-self:center}.self-baseline-l{align-self:baseline}.self-stretch-l{align-self:stretch}.justify-start-l{justify-content:flex-start}.justify-end-l{justify-content:flex-end}.justify-center-l{justify-content:center}.justify-between-l{justify-content:space-between}.justify-around-l{justify-content:space-around}.content-start-l{align-content:flex-start}.content-end-l{align-content:flex-end}.content-center-l{align-content:center}.content-between-l{align-content:space-between}.content-around-l{align-content:space-around}.content-stretch-l{align-content:stretch}.order-0-l{order:0}.order-1-l{order:1}.order-2-l{order:2}.order-3-l{order:3}.order-4-l{order:4}.order-5-l{order:5}.order-6-l{order:6}.order-7-l{order:7}.order-8-l{order:8}.order-last-l{order:99999}.fl-l{float:left}.fl-l,.fr-l{display:inline}.fr-l{float:right}.fn-l{float:none}.i-l{font-style:italic}.fs-normal-l{font-style:normal}.normal-l{font-weight:400}.b-l{font-weight:700}.fw1-l{font-weight:100}.fw2-l{font-weight:200}.fw3-l{font-weight:300}.fw4-l{font-weight:400}.fw5-l{font-weight:500}.fw6-l{font-weight:600}.fw7-l{font-weight:700}.fw8-l{font-weight:800}.fw9-l{font-weight:900}.h1-l{height:1rem}.h2-l{height:2rem}.h3-l{height:4rem}.h4-l{height:8rem}.h5-l{height:16rem}.h-25-l{height:25%}.h-50-l{height:50%}.h-75-l{height:75%}.h-100-l{height:100%}.h-auto-l{height:auto}.h-inherit-l{height:inherit}.tracked-l{letter-spacing:.16em}.tracked-tight-l{letter-spacing:-.05em}.tracked-mega-l{letter-spacing:.32em}.lh-solid-l{line-height:1}.lh-title-l{line-height:1.3}.lh-copy-l{line-height:1.6}.mw-100-l{max-width:100%}.mw1-l{max-width:1rem}.mw2-l{max-width:2rem}.mw3-l{max-width:4rem}.mw4-l{max-width:8rem}.mw5-l{max-width:16rem}.mw6-l{max-width:32rem}.mw7-l{max-width:48rem}.mw8-l{max-width:64rem}.mw9-l{max-width:96rem}.mw-none-l{max-width:none}.w1-l{width:1rem}.w2-l{width:2rem}.w3-l{width:4rem}.w4-l{width:8rem}.w5-l{width:16rem}.w-10-l{width:10%}.w-20-l{width:20%}.w-25-l{width:25%}.w-33-l{width:33%}.w-34-l{width:34%}.w-40-l{width:40%}.w-50-l{width:50%}.w-60-l{width:60%}.w-75-l{width:75%}.w-80-l{width:80%}.w-100-l{width:100%}.w-auto-l{width:auto}.overflow-visible-l{overflow:visible}.overflow-hidden-l{overflow:hidden}.overflow-scroll-l{overflow:scroll}.overflow-auto-l{overflow:auto}.overflow-x-visible-l{overflow-x:visible}.overflow-x-hidden-l{overflow-x:hidden}.overflow-x-scroll-l{overflow-x:scroll}.overflow-x-auto-l{overflow-x:auto}.overflow-y-visible-l{overflow-y:visible}.overflow-y-hidden-l{overflow-y:hidden}.overflow-y-scroll-l{overflow-y:scroll}.overflow-y-auto-l{overflow-y:auto}.static-l{position:static}.relative-l{position:relative}.absolute-l{position:absolute}.fixed-l{position:fixed}.pa0-l{padding:0}.pa1-l{padding:.25rem}.pa2-l{padding:.5rem}.pa3-l{padding:1rem}.pa4-l{padding:2rem}.pa5-l{padding:4rem}.pa6-l{padding:8rem}.pa7-l{padding:16rem}.pl0-l{padding-left:0}.pl1-l{padding-left:.25rem}.pl2-l{padding-left:.5rem}.pl3-l{padding-left:1rem}.pl4-l{padding-left:2rem}.pl5-l{padding-left:4rem}.pl6-l{padding-left:8rem}.pl7-l{padding-left:16rem}.pr0-l{padding-right:0}.pr1-l{padding-right:.25rem}.pr2-l{padding-right:.5rem}.pr3-l{padding-right:1rem}.pr4-l{padding-right:2rem}.pr5-l{padding-right:4rem}.pr6-l{padding-right:8rem}.pr7-l{padding-right:16rem}.pb0-l{padding-bottom:0}.pb1-l{padding-bottom:.25rem}.pb2-l{padding-bottom:.5rem}.pb3-l{padding-bottom:1rem}.pb4-l{padding-bottom:2rem}.pb5-l{padding-bottom:4rem}.pb6-l{padding-bottom:8rem}.pb7-l{padding-bottom:16rem}.pt0-l{padding-top:0}.pt1-l{padding-top:.25rem}.pt2-l{padding-top:.5rem}.pt3-l{padding-top:1rem}.pt4-l{padding-top:2rem}.pt5-l{padding-top:4rem}.pt6-l{padding-top:8rem}.pt7-l{padding-top:16rem}.pv0-l{padding-top:0;padding-bottom:0}.pv1-l{padding-top:.25rem;padding-bottom:.25rem}.pv2-l{padding-top:.5rem;padding-bottom:.5rem}.pv3-l{padding-top:1rem;padding-bottom:1rem}.pv4-l{padding-top:2rem;padding-bottom:2rem}.pv5-l{padding-top:4rem;padding-bottom:4rem}.pv6-l{padding-top:8rem;padding-bottom:8rem}.pv7-l{padding-top:16rem;padding-bottom:16rem}.ph0-l{padding-left:0;padding-right:0}.ph1-l{padding-left:.25rem;padding-right:.25rem}.ph2-l{padding-left:.5rem;padding-right:.5rem}.ph3-l{padding-left:1rem;padding-right:1rem}.ph4-l{padding-left:2rem;padding-right:2rem}.ph5-l{padding-left:4rem;padding-right:4rem}.ph6-l{padding-left:8rem;padding-right:8rem}.ph7-l{padding-left:16rem;padding-right:16rem}.ma0-l{margin:0}.ma1-l{margin:.25rem}.ma2-l{margin:.5rem}.ma3-l{margin:1rem}.ma4-l{margin:2rem}.ma5-l{margin:4rem}.ma6-l{margin:8rem}.ma7-l{margin:16rem}.ml0-l{margin-left:0}.ml1-l{margin-left:.25rem}.ml2-l{margin-left:.5rem}.ml3-l{margin-left:1rem}.ml4-l{margin-left:2rem}.ml5-l{margin-left:4rem}.ml6-l{margin-left:8rem}.ml7-l{margin-left:16rem}.mr0-l{margin-right:0}.mr1-l{margin-right:.25rem}.mr2-l{margin-right:.5rem}.mr3-l{margin-right:1rem}.mr4-l{margin-right:2rem}.mr5-l{margin-right:4rem}.mr6-l{margin-right:8rem}.mr7-l{margin-right:16rem}.mb0-l{margin-bottom:0}.mb1-l{margin-bottom:.25rem}.mb2-l{margin-bottom:.5rem}.mb3-l{margin-bottom:1rem}.mb4-l{margin-bottom:2rem}.mb5-l{margin-bottom:4rem}.mb6-l{margin-bottom:8rem}.mb7-l{margin-bottom:16rem}.mt0-l{margin-top:0}.mt1-l{margin-top:.25rem}.mt2-l{margin-top:.5rem}.mt3-l{margin-top:1rem}.mt4-l{margin-top:2rem}.mt5-l{margin-top:4rem}.mt6-l{margin-top:8rem}.mt7-l{margin-top:16rem}.mv0-l{margin-top:0;margin-bottom:0}.mv1-l{margin-top:.25rem;margin-bottom:.25rem}.mv2-l{margin-top:.5rem;margin-bottom:.5rem}.mv3-l{margin-top:1rem;margin-bottom:1rem}.mv4-l{margin-top:2rem;margin-bottom:2rem}.mv5-l{margin-top:4rem;margin-bottom:4rem}.mv6-l{margin-top:8rem;margin-bottom:8rem}.mv7-l{margin-top:16rem;margin-bottom:16rem}.mh0-l{margin-left:0;margin-right:0}.mh1-l{margin-left:.25rem;margin-right:.25rem}.mh2-l{margin-left:.5rem;margin-right:.5rem}.mh3-l{margin-left:1rem;margin-right:1rem}.mh4-l{margin-left:2rem;margin-right:2rem}.mh5-l{margin-left:4rem;margin-right:4rem}.mh6-l{margin-left:8rem;margin-right:8rem}.mh7-l{margin-left:16rem;margin-right:16rem}.strike-l{text-decoration:line-through}.underline-l{text-decoration:underline}.no-underline-l{text-decoration:none}.tl-l{text-align:left}.tr-l{text-align:right}.tc-l{text-align:center}.ttc-l{text-transform:capitalize}.ttl-l{text-transform:lowercase}.ttu-l{text-transform:uppercase}.ttn-l{text-transform:none}.f-6-l,.f-headline-l{font-size:6rem}.f-5-l,.f-subheadline-l{font-size:5rem}.f1-l{font-size:3rem}.f2-l{font-size:2.25rem}.f3-l{font-size:1.5rem}.f4-l{font-size:1.25rem}.f5-l{font-size:1rem}.f6-l{font-size:.875rem}.measure-l{max-width:30em}.measure-wide-l{max-width:34em}.measure-narrow-l{max-width:20em}.indent-l{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-l{font-variant:small-caps}.truncate-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.clip-l{position:fixed!important;position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal-l{white-space:normal}.nowrap-l{white-space:nowrap}.pre-l{white-space:pre}.v-base-l{vertical-align:baseline}.v-mid-l{vertical-align:middle}.v-top-l{vertical-align:top}.v-btm-l{vertical-align:bottom}}
-
diff --git a/routes/index.js b/routes/index.js
deleted file mode 100644
index 42af1dfb..00000000
--- a/routes/index.js
+++ /dev/null
@@ -1,105 +0,0 @@
-"use strict";
-
-const express = require("express");
-const router = express.Router();
-const browserslist = require("browserslist");
-const bv = require("browserslist/package.json").version;
-const cv = require("caniuse-db/package.json").version;
-const caniuse = require("caniuse-db/data.json").agents;
-
-let caniuseRegion;
-
-function getCoverage(data, version) {
- const lastVersion = Object.keys(data).sort((a, b) => {
- return parseInt(b) - parseInt(a);
- })[0];
- // If specific version coverage is missing, fall back to "version zero"
- return data[version] !== undefined ? data[version] : data[lastVersion];
-}
-
-function getRegionCoverage(region, id, version) {
- if (!caniuseRegion) {
- caniuseRegion = require(`caniuse-db/region-usage-json/${region}.json`);
- }
-
- return getCoverage(caniuseRegion.data[id], version);
-}
-
-/* GET home page. */
-router.get("/", (req, res) => {
- const query = req.query.q || "defaults";
- const queryHasIn = query.match(/ in ((?:alt-)?[A-Za-z]{2})(?:,|$)/);
-
- const region = queryHasIn ? queryHasIn[1] : undefined;
-
- let bl = null;
- try {
- // Remove quotes to allow users to copy multiline strings,
- // e.g., from their package.json file.
- const queryWithoutQuotes = query.replace(/"/g, "");
- bl = browserslist(queryWithoutQuotes);
- } catch (e) {
- // Error
- return res.render("index", {
- compatible: null,
- query,
- description:
- "A page to display compatible browsers from a browserslist string.",
- error: e,
- });
- }
-
- const compatible = {};
-
- if (bl) {
- bl.map((b) => {
- b = b.split(" ");
-
- const id = b[0];
- const version = b[1];
-
- let coverage;
- let type;
- let name;
-
- // "Can I use" doesn't have stats for Node
- if (id === "node") {
- type = "server";
- name = "Node";
- } else {
- const db = caniuse[id];
-
- coverage = region
- ? getRegionCoverage(region, id, version)
- : getCoverage(db.usage_global, version);
- type = db.type;
- name = db.browser;
- }
-
- if (!compatible[type]) {
- compatible[type] = [];
- }
-
- compatible[type].push({
- version,
- id,
- name,
- coverage,
- logo: `/images/${id}.png`,
- });
- });
- }
-
- res.render("index", {
- compatible,
- query,
- bv,
- cv,
- coverage: browserslist.coverage(bl, region),
- description:
- "A page to display compatible browsers from a browserslist string.",
- region: region || "Global",
- });
-});
-
-module.exports = router;
diff --git a/script/deploy b/script/deploy
deleted file mode 100755
index ecca4cb2..00000000
--- a/script/deploy
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-set -e
-now rm -y browserlist
-now --public
-now alias browserl.ist
-now alias browsersl.ist
diff --git a/server/handlers/api-browsers.js b/server/handlers/api-browsers.js
new file mode 100644
index 00000000..6ceeecf1
--- /dev/null
+++ b/server/handlers/api-browsers.js
@@ -0,0 +1,22 @@
+import { URL } from 'node:url'
+
+import getBrowsers, {
+ QUERY_DEFAULTS,
+ REGION_GLOBAL
+} from '../lib/get-browsers.js'
+import { sendResponseAPI } from '../lib/send-response.js'
+
+export default async function handleAPIBrowsers(req, res) {
+ let { searchParams: params } = new URL(req.url, `http://${req.headers.host}/`)
+
+ let query = params.get('q') || QUERY_DEFAULTS
+ let queryWithoutQuotes = query.replace(/'/g, '')
+
+ let region = params.get('region') || REGION_GLOBAL
+
+ try {
+ sendResponseAPI(res, 200, await getBrowsers(queryWithoutQuotes, region))
+ } catch (error) {
+ sendResponseAPI(res, 400, { message: error.message })
+ }
+}
diff --git a/server/handlers/main.js b/server/handlers/main.js
new file mode 100644
index 00000000..6c7e64a5
--- /dev/null
+++ b/server/handlers/main.js
@@ -0,0 +1,24 @@
+import { URL } from 'node:url'
+
+import getFileData from '../lib/get-file-data.js'
+import { sendResponse, sendResponseError } from '../lib/send-response.js'
+
+const responseHeaders = {
+ 'Content-Type': 'text/html',
+ 'Cache-Control': 'public, max-age=300, must-revalidate'
+}
+
+export default async function handleMain(req, res) {
+ let filePath = new URL('../../client/dist/index.html', import.meta.url)
+
+ try {
+ let { data } = await getFileData(filePath, true)
+ sendResponse(res, 200, responseHeaders, data)
+ } catch (error) {
+ if (error.httpStatus) {
+ sendResponseError(res, error.httpStatus, error.message)
+ } else {
+ sendResponseError(res, 500, 'Internal Server Error')
+ }
+ }
+}
diff --git a/server/handlers/static.js b/server/handlers/static.js
new file mode 100644
index 00000000..9e5fbd89
--- /dev/null
+++ b/server/handlers/static.js
@@ -0,0 +1,50 @@
+import { URL } from 'node:url'
+
+import { sendResponse, sendResponseError } from '../lib/send-response.js'
+import getFileData from '../lib/get-file-data.js'
+
+const CLIENT_DIR = '../../client'
+const DIST_DIR = '/dist'
+const MIME_TYPES = {
+ '.html': 'text/html',
+ '.js': 'text/javascript',
+ '.css': 'text/css',
+ '.json': 'application/json',
+ '.webmanifest': 'application/manifest+json',
+ '.png': 'image/png',
+ '.jpg': 'image/jpg',
+ '.svg': 'image/svg+xml',
+ '.ico': 'image/x-icon'
+}
+
+export default async function handleStatic(req, res) {
+ let filePath = new URL(`${CLIENT_DIR}${DIST_DIR}${req.url}`, import.meta.url)
+
+ try {
+ let shouldBeCached = req.url === '/favicon.ico'
+ let { name, ext, size, data } = await getFileData(filePath, shouldBeCached)
+ let resHeaders = {
+ 'Cache-Control': getCacheControl(name),
+ 'Content-Type': getContentType(ext),
+ 'Content-Length': size
+ }
+ sendResponse(res, 200, resHeaders, data)
+ } catch (error) {
+ if (error.httpStatus) {
+ sendResponseError(res, error.httpStatus, error.message)
+ } else {
+ sendResponseError(res, 500, 'Internal Server Error')
+ }
+ }
+}
+
+function getContentType(ext) {
+ return MIME_TYPES[ext] || 'application/octet-stream'
+}
+
+function getCacheControl(name) {
+ let hasFileCacheBuster = /\.(\w{8})$/.test(name)
+ return hasFileCacheBuster
+ ? 'public, max-age=31536000, immutable'
+ : 'max-age=3600'
+}
diff --git a/server/index.js b/server/index.js
new file mode 100644
index 00000000..5894145b
--- /dev/null
+++ b/server/index.js
@@ -0,0 +1,32 @@
+import http from 'node:http'
+import { URL } from 'node:url'
+
+import handleMain from './handlers/main.js'
+import handleAPIBrowsers from './handlers/api-browsers.js'
+import handleStatic from './handlers/static.js'
+
+const PORT = process.env.PORT || 5000
+
+const App = http.createServer(async (req, res) => {
+ let { pathname } = new URL(req.url, `http://${req.headers.host}/`)
+
+ switch (pathname) {
+ case '/':
+ handleMain(req, res)
+ break
+
+ case '/api/browsers':
+ handleAPIBrowsers(req, res)
+ break
+
+ default:
+ handleStatic(req, res)
+ break
+ }
+})
+
+App.listen(PORT, () => {
+ process.stdout.write(`Server listening on a port http://localhost:${PORT}/\n`)
+})
+
+export default App
diff --git a/server/lib/get-browsers.js b/server/lib/get-browsers.js
new file mode 100644
index 00000000..27d53cb5
--- /dev/null
+++ b/server/lib/get-browsers.js
@@ -0,0 +1,139 @@
+import { agents as caniuseAgents, region as caniuseRegion } from 'caniuse-lite'
+import { readFileSync } from 'node:fs'
+import browserslist from 'browserslist'
+import { URL } from 'node:url'
+
+let { version: bv } = importJSON('../node_modules/browserslist/package.json')
+let { version: cv } = importJSON('../node_modules/caniuse-lite/package.json')
+
+export const QUERY_DEFAULTS = 'defaults'
+export const REGION_GLOBAL = 'Global'
+
+export default async function getBrowsers(query, region) {
+ let loadBrowsersData = async (resolve, reject) => {
+ let browsersByQuery = []
+
+ try {
+ browsersByQuery = browserslist(query)
+ } catch (error) {
+ reject(
+ error.browserslist
+ ? error
+ : new Error(`Unknown browser query \`${query}\`.`)
+ )
+ return
+ }
+
+ let browsersGroups = {}
+ let browsersGroupsKeys = []
+
+ for (let browser of browsersByQuery) {
+ if (browsersGroupsKeys.includes(browser)) {
+ return
+ }
+
+ browsersGroupsKeys.push(browser)
+ let [id, version] = browser.split(' ')
+ let versionCoverage = null
+
+ if (id !== 'node') {
+ try {
+ versionCoverage =
+ region === REGION_GLOBAL
+ ? getGlobalCoverage(id, version)
+ : await getRegionCoverage(id, version, region)
+ } catch (error) {
+ reject(error)
+ }
+ }
+
+ let versionData = { [`${version}`]: roundNumber(versionCoverage) }
+
+ if (!browsersGroups[id]) {
+ browsersGroups[id] = { versions: versionData }
+ } else {
+ Object.assign(browsersGroups[id].versions, versionData)
+ }
+ }
+
+ let browsers = Object.entries(browsersGroups)
+ .map(([id, { versions }]) => {
+ let name
+ let coverage
+
+ // The Node.js is not in the Can I Use db
+ if (id === 'node') {
+ name = 'Node'
+ coverage = null
+ } else {
+ name = caniuseAgents[id].browser
+ coverage = roundNumber(
+ Object.values(versions).reduce((a, b) => a + b, 0)
+ )
+ }
+
+ return {
+ id,
+ name,
+ coverage,
+ versions
+ }
+ })
+ .sort((a, b) => b.coverage - a.coverage)
+
+ let coverage
+
+ try {
+ coverage = roundNumber(browserslist.coverage(browsersByQuery, region))
+ } catch (error) {
+ reject(error)
+ }
+
+ resolve({
+ query,
+ region,
+ coverage,
+ versions: {
+ browserslist: bv,
+ caniuse: cv
+ },
+ browsers
+ })
+ }
+
+ return new Promise(loadBrowsersData)
+}
+
+function getGlobalCoverage(id, version) {
+ return getCoverage(caniuseAgents[id].usage_global, version)
+}
+
+async function getRegionCoverage(id, version, region) {
+ try {
+ if (region.includes('/')) {
+ throw new Error(`Invalid symbols in region name \`${region}\`.`)
+ }
+
+ let { default: regionData } = await import(
+ `caniuse-lite/data/regions/${region}.js`
+ )
+ return getCoverage(caniuseRegion(regionData)[id], version)
+ } catch (e) {
+ throw new Error(`Unknown region name \`${region}\`.`)
+ }
+}
+
+function getCoverage(data, version) {
+ let [lastVersion] = Object.keys(data).sort((a, b) => Number(b) - Number(a))
+
+ // If specific version coverage is missing, fall back to 'version zero'
+ return data[version] !== undefined ? data[version] : data[lastVersion]
+}
+
+function roundNumber(value) {
+ return Math.round(value * 100) / 100
+}
+
+function importJSON(path) {
+ return JSON.parse(readFileSync(new URL(path, import.meta.url)))
+}
diff --git a/server/lib/get-file-data.js b/server/lib/get-file-data.js
new file mode 100644
index 00000000..d9460433
--- /dev/null
+++ b/server/lib/get-file-data.js
@@ -0,0 +1,37 @@
+import { readFile, stat } from 'node:fs/promises'
+import { existsSync } from 'node:fs'
+import { parse } from 'node:path'
+
+const IS_PRODUCTION = process.env.NODE_ENV === 'production'
+const CACHE = {}
+
+export default async function getFileData(filePath, shouldBeCached = false) {
+ shouldBeCached = shouldBeCached && IS_PRODUCTION
+
+ if (shouldBeCached && filePath in CACHE) {
+ return CACHE[filePath]
+ }
+
+ if (!existsSync(filePath)) {
+ let error = new Error('Not Found')
+ error.httpStatus = 404
+ throw error
+ }
+
+ let { name, ext } = parse(filePath.pathname)
+ let { size } = await stat(filePath)
+ let data = await readFile(filePath)
+
+ let fileData = {
+ name,
+ ext,
+ size,
+ data
+ }
+
+ if (shouldBeCached) {
+ CACHE[filePath] = fileData
+ }
+
+ return fileData
+}
diff --git a/server/lib/send-response.js b/server/lib/send-response.js
new file mode 100644
index 00000000..25d73207
--- /dev/null
+++ b/server/lib/send-response.js
@@ -0,0 +1,24 @@
+export function sendResponse(res, status, headers, data) {
+ res.writeHead(status, headers)
+ res.write(data)
+ res.end()
+}
+
+export function sendResponseAPI(res, status, data) {
+ let JSONData = JSON.stringify(data)
+
+ res.writeHead(status, {
+ 'Access-Control-Allow-Origin': '*',
+ 'Content-Type': 'text/json',
+ 'Content-Length': JSONData.length
+ })
+ res.write(JSONData)
+ res.end()
+}
+
+export function sendResponseError(res, status, message) {
+ res.writeHead(status, {
+ 'Content-Type': 'text/plain'
+ })
+ res.end(message)
+}
diff --git a/server/package.json b/server/package.json
new file mode 100644
index 00000000..3e46a7b9
--- /dev/null
+++ b/server/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "browserl.ist-server",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "start": "node index.js",
+ "test": "pnpm -r build && node --test test/*.test.js"
+ },
+ "dependencies": {
+ "browserslist": "^4.21.3",
+ "caniuse-lite": "^1.0.30001375"
+ }
+}
diff --git a/server/test/browsers.test.js b/server/test/browsers.test.js
new file mode 100644
index 00000000..a0525d87
--- /dev/null
+++ b/server/test/browsers.test.js
@@ -0,0 +1,50 @@
+import test from 'node:test'
+import { equal, notEqual, ok, match } from 'node:assert'
+
+import getBrowsers from '../lib/get-browsers.js'
+
+test('Throws error for wrong browserslist `query`', async () => {
+ let error
+ try {
+ await getBrowsers('wrong', 'Global')
+ } catch (e) {
+ error = e
+ }
+ ok(error instanceof Error)
+ match(error.message, /Unknown browser query/)
+})
+
+test('Throws error for wrong Can I Use `region`', async () => {
+ let error
+ try {
+ await getBrowsers('>0%', 'XX')
+ } catch (e) {
+ error = e
+ }
+ ok(error instanceof Error)
+ match(error.message, /Unknown region name/)
+})
+
+test('Returns Node.js versions without coverage`', async () => {
+ let data = await getBrowsers('Node > 0', 'Global')
+
+ equal(data.browsers[0].name, 'Node')
+ equal(data.browsers[0].coverage, null)
+})
+
+test('Сoverage of all browsers should differ in different regions', async () => {
+ let continentData = await getBrowsers('>1%', 'Global')
+ let countryData = await getBrowsers('>1%', 'IT')
+
+ notEqual(continentData.coverage, countryData.coverage)
+})
+
+test('Сoverage for browser should differ in different regions', async () => {
+ let continentData = await getBrowsers('last 2 Chrome versions', 'alt-eu')
+ let countryData = await getBrowsers('last 2 Chrome versions', 'NP')
+
+ let continentBrowser = continentData.browsers[0]
+ let countryBrowser = countryData.browsers[0]
+
+ notEqual(continentBrowser.coverage, countryBrowser.coverage)
+})
diff --git a/server/test/index.test.js b/server/test/index.test.js
new file mode 100644
index 00000000..9c726706
--- /dev/null
+++ b/server/test/index.test.js
@@ -0,0 +1,83 @@
+import { equal, match } from 'node:assert'
+import { URL } from 'node:url'
+import test from 'node:test'
+
+import App from '../index.js'
+
+const base = `http://localhost:${App.address().port}/`
+
+test('Integration tests', async t => {
+ await t.test(
+ 'responses `defaults` query for `/browsers` route without `q` param',
+ async () => {
+ let url = new URL(`api/browsers`, base)
+ let response = await fetch(url)
+ let data = await response.json()
+ equal(data.query, 'defaults')
+ }
+ )
+
+ await t.test(
+ 'responses `Global` region for `/browsers` route without `region` param',
+ async () => {
+ let url = new URL(`api/browsers`, base)
+ let response = await fetch(url)
+ let data = await response.json()
+ equal(data.region, 'Global')
+ }
+ )
+
+ await t.test('responses status 200 for `/browsers` route', async () => {
+ let url = new URL(`api/browsers`, base)
+ let response = await fetch(url)
+ equal(response.status, 200)
+ })
+
+ await t.test(
+ 'responses 400 for `/browsers` route with wrong `q` param',
+ async () => {
+ let url = new URL(`api/browsers?q=wrong-query`, base)
+ let response = await fetch(url)
+ let error = await response.json()
+ equal(response.status, 400)
+ match(error.message, /Unknown/)
+ }
+ )
+
+ await t.test('responses 404 for unknown route', async () => {
+ let url = new URL(`wrong-route`, base)
+ let response = await fetch(url)
+ let text = await response.text()
+ equal(response.status, 404)
+ match(text, /Not Found/)
+ })
+
+ await t.test('opens the file index.html by the URL `/`', async () => {
+ let url = new URL('', base)
+ let response = await fetch(url)
+ let html = await response.text()
+ equal(response.status, 200)
+ match(html, /Browserslist/)
+ match(html, / {
+ let url = new URL('/favicon.ico', base)
+ let response = await fetch(url)
+ equal(response.status, 200)
+ equal(response.headers.get('Content-Type'), 'image/x-icon')
+ }
+ )
+
+ await t.test('loads static `/favicon.ico` with 1 hour cache', async () => {
+ let url = new URL('/favicon.ico', base)
+ let response = await fetch(url)
+ equal(response.status, 200)
+ equal(response.headers.get('Cache-Control'), 'max-age=3600')
+ })
+
+ App.closeAllConnections()
+ App.close()
+})
diff --git a/simple-git-hooks.json b/simple-git-hooks.json
new file mode 100644
index 00000000..f7b0c2ff
--- /dev/null
+++ b/simple-git-hooks.json
@@ -0,0 +1,3 @@
+{
+ "pre-commit": "./node_modules/.bin/nano-staged --config ./nano-staged.json"
+}
diff --git a/vercel.json b/vercel.json
deleted file mode 100644
index 60121507..00000000
--- a/vercel.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "version": 2,
- "rewrites": [{ "source": "/(.*)", "destination": "/api/server" }]
-}
diff --git a/views/error.pug b/views/error.pug
deleted file mode 100644
index 51ec12c6..00000000
--- a/views/error.pug
+++ /dev/null
@@ -1,6 +0,0 @@
-extends layout
-
-block content
- h1= message
- h2= error.status
- pre #{error.stack}
diff --git a/views/index.pug b/views/index.pug
deleted file mode 100644
index 6ffafa26..00000000
--- a/views/index.pug
+++ /dev/null
@@ -1,42 +0,0 @@
-extends layout
-
-block content
- div(class="tc bg-neon-carrot plum bb b--black-10 pa4 pa5-ns")
- h1(class="f2 f-headline-l f1-ns fw6 mid-gray ma0")
- a(href="/") browsersl.ist
- p(class="ma0 mt2 mb4 mb5-ns") #{description}
- form(method="get" action="/" class="cf dt-ns w-100 my4 f5 f4-l")
- div(class="fl dtc-ns w-100 w-80-ns mb2 mb0-ns pr2-ns")
- input(class="pa2 ba b--black-30 code br1 border-box w-100 lh-title" name="q" value= query)
- div(class="fl dtc-ns w-100 w-20-ns")
- button(type=submit class="bg-plum neon-carrot b bg-plum--hover pa2 ba b--black-30 br1 db w-100 lh-title border-box pointer") Show #[span(class="dn-m") Browsers]
- div(class="dt-ns w-100 mw8 center")
- if compatible
- - const columns = Object.keys(compatible).length
- each browsers, platform in compatible
- div(class=`dtc-l pa2 ${columns === 3 ? 'w-third' : 'w-50-l'} border-box`)
- h2(class="f4 f3-ns ma0 mt4 mb4 tc ttc")
- if platform === 'server'
- | Node.js #{platform}s
- else
- | #{platform} browsers
- ul(class="ma0 list pa3")
- each browser in browsers
- li(class="ma0 mb3 lh-copy")
- img(src=browser.logo class="v-mid mr2" alt="" height="34" width="34")
- span(class="mr1 v-mid") #{browser.name}
- span(class="mr1 v-mid") #{browser.version}
- span(class="v-mid fr")
- small
- if isFinite(browser.coverage)
- | #{Math.round(browser.coverage * 100) / 100}%
- else
- | Unknown coverage
- else if error != null
- h2(class="f4 f3-ns ma0 mv5 tc ttc") #{error}
- div(class="tc bg-neon-carrot plum bb b--black-10 pa2 pa3-ns mt4")
- if compatible
- | #{region} coverage:
- strong(class="ml1") #{Math.round(coverage * 100) / 100}%
- else
- | Unknown coverage
diff --git a/views/layout.pug b/views/layout.pug
deleted file mode 100644
index 8c0b63fc..00000000
--- a/views/layout.pug
+++ /dev/null
@@ -1,19 +0,0 @@
-doctype html
-html(lang='en')
- head
- meta(charset="utf-8")
- title browserl.ist: #{description}
- meta(name="description" content=description)
- meta(http-equiv="X-UA-Compatible" content="IE=Edge")
- meta(name="author" content="@browserslist")
- meta(name="viewport" content="width=device-width, initial-scale=1")
- link(rel='shortcut icon', href='/images/favicon.png', type='image/png')
- link(rel='stylesheet', href='/stylesheets/tachyons.min.css')
- link(rel='stylesheet', href='/stylesheets/style.css')
- body(class="sans-serif f4")
- block content
- div(class="pa5 f6 lh-copy")
- span(class="mr4 db di-ns mb2 mb0-ns") Made by #[a(href="https://twitter.com/browserslist") browserslist]
- span(class="mr4 db di-ns mb2 mb0-ns") Code on #[a(href="https://github.com/browserslist/browserl.ist") GitHub]
- span(class="mr4 db di-ns mb2 mb0-ns") Functionality provided by #[a(href="https://github.com/browserslist/browserslist") browserslist] #{bv}
- span(class="mr4 db di-ns mb2 mb0-ns") Data provided by #[a(href="https://github.com/Fyrd/caniuse") caniuse-db] #{cv}