diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c05565b6a..63c5e4b2d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,30 +16,47 @@ jobs: os: [ubuntu-latest, windows-latest] steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - node-version: '14' + node-version: 16 + + - name: pnpm setup + uses: pnpm/action-setup@v2.2.4 + with: + version: 7.17.0 + run_install: true - name: cache pnpm modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}- - - name: pnpm setup - uses: pnpm/action-setup@v2.1.0 - with: - version: 6.31.0 - run_install: true + - name: Install dependencies + run: pnpm install + + - name: Install E2E test browsers + if: runner.os != 'Windows' + run: pnpm dlx playwright install --with-deps chromium - - run: pnpm run build - run: pnpm run update + - run: pnpm run build - run: pnpm run gen working-directory: ./packages/site - run: pnpm run test - env: - CI: true + + - name: Run E2E tests + if: runner.os != 'Windows' + run: pnpm run test:e2e + + - name: Upload E2E results + uses: actions/upload-artifact@v3 + if: runner.os != 'Windows' + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f38e38cde..605d2334a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,26 +8,32 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - node-version: '14' + node-version: 16 - name: cache pnpm modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}- - - uses: pnpm/action-setup@v2.1.0 + - name: pnpm setup + uses: pnpm/action-setup@v2.2.4 with: - version: 6.31.0 + version: 7.17.0 run_install: true - - run: pnpm run build - run: pnpm run update + - run: pnpm run build + + - run: pnpm run test + + - name: Run E2E tests + run: pnpm run test:e2e - name: Deploy npm Packages run: npx pleb publish diff --git a/.gitignore b/.gitignore index d19810276..a7d26a37e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules tsconfig.tsbuildinfo tmp -.DS_Store \ No newline at end of file +.DS_Store +playwright-report/ \ No newline at end of file diff --git a/package.json b/package.json index cd6878523..bcd3c5e27 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,8 @@ "dev": "pnpm -r --parallel watch", "fmt": "prettier --write packages/**/*.ts", "test": "cross-env NODE_OPTIONS=--max-old-space-size=4096 jest --colors", + "test:e2e": "npm run test:e2e:localserver & pnpm dlx playwright test", + "test:e2e:localserver": "node ./scripts/e2e/local-server.mjs", "update": "npm run update:themes && npm run update:grammars", "update:themes": "bash ./scripts/pullThemes.sh", "update:grammars": "bash ./scripts/pullGrammars.sh" @@ -21,7 +23,8 @@ ] }, "devDependencies": { - "@rollup/plugin-commonjs": "^23.0.7", + "@playwright/test": "^1.29.0", + "@rollup/plugin-commonjs": "^24.0.0", "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-terser": "^0.2.1", @@ -47,6 +50,7 @@ "rollup-plugin-copy": "^3.4.0", "rollup-plugin-dts": "^5.1.1", "rollup-plugin-esbuild": "^5.0.0", + "superstatic": "^9.0.0", "ts-jest": "^29.0.5", "tsup": "^6.5.0", "typescript": "^4.9.4", @@ -55,6 +59,6 @@ }, "license": "MIT", "dependencies": { - "esbuild": "^0.16.7" + "esbuild": "^0.16.10" } } diff --git a/packages/renderer-path/package.json b/packages/renderer-path/package.json index 12881e1b1..597534155 100644 --- a/packages/renderer-path/package.json +++ b/packages/renderer-path/package.json @@ -25,10 +25,10 @@ "watch": "rollup -c -w" }, "peerDependencies": { - "shiki": "^0.12.0" + "shiki": "^0.12.1" }, "devDependencies": { - "@types/node": "^18.11.15", + "@types/node": "^18.11.17", "@types/opentype.js": "^1.3.4", "opentype.js": "^1.3.4", "shiki": "^0.13.0" diff --git a/packages/renderer-svg/package.json b/packages/renderer-svg/package.json index 5173ccb44..5d9dff086 100644 --- a/packages/renderer-svg/package.json +++ b/packages/renderer-svg/package.json @@ -25,11 +25,11 @@ }, "peerDependencies": { "playwright": "^1.9.2", - "shiki": "^0.12.0" + "shiki": "^0.12.1" }, "devDependencies": { - "@types/node": "^18.11.15", - "playwright": "^1.28.1", + "@types/node": "^18.11.17", + "playwright": "^1.29.0", "shiki": "^0.13.0" } } diff --git a/packages/shiki/.gitignore b/packages/shiki/.gitignore new file mode 100644 index 000000000..75e854d8d --- /dev/null +++ b/packages/shiki/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/packages/shiki/package.json b/packages/shiki/package.json index d2628c5bd..8397db3cd 100644 --- a/packages/shiki/package.json +++ b/packages/shiki/package.json @@ -37,7 +37,7 @@ "vscode-textmate": "^8.0.0" }, "devDependencies": { - "@types/node": "^18.11.15" + "@types/node": "^18.11.17" }, "browser": { "fs": false, diff --git a/packages/shiki/rollup.config.mjs b/packages/shiki/rollup.config.mjs index 975e8aa65..101eb2303 100644 --- a/packages/shiki/rollup.config.mjs +++ b/packages/shiki/rollup.config.mjs @@ -57,7 +57,6 @@ export default defineConfig([ }, { input: 'src/index.ts', - external, output: { file: 'dist/index.browser.mjs', format: 'esm', diff --git a/packages/shiki/src/__tests__/__fixtures__/index_browser.html b/packages/shiki/src/__tests__/__fixtures__/index_browser.html new file mode 100644 index 000000000..84c1e5022 --- /dev/null +++ b/packages/shiki/src/__tests__/__fixtures__/index_browser.html @@ -0,0 +1,20 @@ + + + Test Browser + + + + +
+ + diff --git a/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_cdn.html b/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_cdn.html new file mode 100644 index 000000000..7cf28c696 --- /dev/null +++ b/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_cdn.html @@ -0,0 +1,22 @@ + + + Test Browser - Custom CDN + + + + +
+ + diff --git a/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_paths.html b/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_paths.html new file mode 100644 index 000000000..743916291 --- /dev/null +++ b/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_paths.html @@ -0,0 +1,25 @@ + + + Test Browser - Custom Paths + + + + +
+ + diff --git a/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_wasm.html b/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_wasm.html new file mode 100644 index 000000000..ba8fc34bd --- /dev/null +++ b/packages/shiki/src/__tests__/__fixtures__/index_browser_custom_wasm.html @@ -0,0 +1,23 @@ + + + Test Browser - Custom Wasm + + + + +
+ + diff --git a/packages/shiki/src/__tests__/__fixtures__/index_jsdelivr.html b/packages/shiki/src/__tests__/__fixtures__/index_jsdelivr.html new file mode 100644 index 000000000..a500c689a --- /dev/null +++ b/packages/shiki/src/__tests__/__fixtures__/index_jsdelivr.html @@ -0,0 +1,20 @@ + + + Test jsDelivr + + + + +
+ + diff --git a/packages/shiki/src/__tests__/__fixtures__/index_unpkg.html b/packages/shiki/src/__tests__/__fixtures__/index_unpkg.html new file mode 100644 index 000000000..dd066450d --- /dev/null +++ b/packages/shiki/src/__tests__/__fixtures__/index_unpkg.html @@ -0,0 +1,20 @@ + + + Test unpgk + + + + +
+ + diff --git a/packages/shiki/src/__tests__/e2e.browser.spec.ts b/packages/shiki/src/__tests__/e2e.browser.spec.ts new file mode 100644 index 000000000..75a176113 --- /dev/null +++ b/packages/shiki/src/__tests__/e2e.browser.spec.ts @@ -0,0 +1,88 @@ +// @ts-check +import { chromium, test, expect } from '@playwright/test' + +test.describe('Browser bundle', async () => { + test(`with default paths loads embedded languages and renders code block`, async () => { + const browser = await chromium.launch() + const page = await browser.newPage() + + let countLanguageRequests = 0 + + page.on('response', response => { + if (response.url().endsWith('tmLanguage.json')) countLanguageRequests++ + }) + + await page.goto(`/index_browser.html`) + + const codeLocator = await page.getByRole('code') + + await expect(codeLocator).toBeVisible() + + expect(countLanguageRequests).toBeGreaterThan(1) + + await browser.close() + }) + + test(`with custom path loads embedded languages and renders code block`, async () => { + const browser = await chromium.launch() + const page = await browser.newPage() + + let countLanguageRequests = 0 + + page.on('response', response => { + if (response.url().endsWith('tmLanguage.json')) countLanguageRequests++ + }) + + await page.goto(`/index_browser_custom_paths.html`) + + const codeLocator = await page.getByRole('code') + + await expect(codeLocator).toBeVisible() + + expect(countLanguageRequests).toBeGreaterThan(1) + + await browser.close() + }) + + test(`with custom setCDN loads embedded languages and renders code block`, async () => { + const browser = await chromium.launch() + const page = await browser.newPage() + + let countLanguageRequests = 0 + + page.on('response', response => { + if (response.url().endsWith('tmLanguage.json')) countLanguageRequests++ + }) + + await page.goto(`/index_browser_custom_cdn.html`) + + const codeLocator = await page.getByRole('code') + + await expect(codeLocator).toBeVisible() + + expect(countLanguageRequests).toBeGreaterThan(1) + + await browser.close() + }) + + test(`with custom setWasm loads embedded languages and renders code block`, async () => { + const browser = await chromium.launch() + const page = await browser.newPage() + + let countLanguageRequests = 0 + + page.on('response', response => { + if (response.url().endsWith('tmLanguage.json')) countLanguageRequests++ + }) + + await page.goto(`/index_browser_custom_wasm.html`) + + const codeLocator = await page.getByRole('code') + + await expect(codeLocator).toBeVisible() + + expect(countLanguageRequests).toBeGreaterThan(1) + + await browser.close() + }) +}) diff --git a/packages/shiki/src/__tests__/e2e.cdn.spec.ts b/packages/shiki/src/__tests__/e2e.cdn.spec.ts new file mode 100644 index 000000000..7ad473295 --- /dev/null +++ b/packages/shiki/src/__tests__/e2e.cdn.spec.ts @@ -0,0 +1,62 @@ +// @ts-check +import { chromium, test, expect } from '@playwright/test' + +const CDN_CONFIGURATIONS = [ + { name: 'jsDelivr', url: 'https://cdn.jsdelivr.net/npm/shiki' }, + { name: 'unpkg', url: 'https://unpkg.com/shiki' } +] + +test.describe('CDN bundle', () => { + for (const cdnConfig of CDN_CONFIGURATIONS) { + test(`for ${cdnConfig.name} loads embedded languages and renders code block`, async ({ + baseURL + }) => { + const browser = await chromium.launch() + const page = await browser.newPage() + + let countLanguageRequests = 0 + + await page.route('**', async route => { + const request = route.request() + + let requestURL = request.url() + + // Checking if all requests go to the CDN + if (!requestURL.endsWith('.html')) { + expect(requestURL).toContain(cdnConfig.url) + requestURL = normalizeURL(requestURL, cdnConfig.url, baseURL) + + // Counting language requests + if (requestURL.endsWith('tmLanguage.json')) countLanguageRequests++ + } + + const response = await page.request.fetch(requestURL) + + route.fulfill({ + response + }) + }) + + await page.goto(`/index_${cdnConfig.name.toLowerCase()}.html`) + + const codeLocator = await page.getByRole('code') + + await expect(codeLocator).toBeVisible() + + expect(countLanguageRequests).toBeGreaterThan(1) + + await browser.close() + }) + } +}) + +function normalizeURL(remoteUrl, cdnUrl, baseUrl) { + // If it's not the base CDN call we're removing the version number + // and modify the request to serve from localhost + if (remoteUrl !== cdnUrl) { + return remoteUrl + .replace(cdnUrl, baseUrl) + .replace(/@[0-9]\.[0-9][0-9]?\.[0-9][0-9]?(\.[0-9][0-9])?/, '') + } + return remoteUrl +} diff --git a/packages/site/gen-palenight.js b/packages/site/gen-palenight.js index 5705e7714..ac868549c 100644 --- a/packages/site/gen-palenight.js +++ b/packages/site/gen-palenight.js @@ -4,7 +4,7 @@ const shiki = require('shiki') shiki .getHighlighter({ - theme: 'material-palenight' + theme: 'material-theme-palenight' }) .then(highlighter => { const md = markdown({ diff --git a/packages/site/index.html b/packages/site/index.html index a2b590d2c..fdf59a1ca 100644 --- a/packages/site/index.html +++ b/packages/site/index.html @@ -5,7 +5,7 @@

shiki

Shiki is a beautiful Syntax Highlighter.

It uses TextMate grammar to tokenize strings, and colors the tokens with VS Code themes. In short, Shiki generates HTML that looks exactly like your code in VS Code, and it works great in your static website generator (or your dynamic website).

It's simple to use:

-
const shiki = require('shiki')
+
const shiki = require('shiki')
 
 shiki.getHighlighter({
   theme: 'nord'
@@ -18,7 +18,7 @@ 

shiki

// </code></pre>

Here's me using Shiki and markdown-it to generate this page:

-
const fs = require('fs')
+
const fs = require('fs')
 const markdown = require('markdown-it')
 const shiki = require('shiki')
 
@@ -45,7 +45,7 @@ 

shiki

})

Why Shiki though? Take a look at this monstrous TextMate grammar. It's what highlights TypeScript code in VS Code. Insane, I know. But it gets the color right.

-
import * as React from 'react';
+
import * as React from 'react';
 import './App.css';
 import Hello from './components/Hello';
 
@@ -69,7 +69,7 @@ 

shiki

export default App;

Besides VS Code, TextMate (of course), Sublime Text and Atom all support TextMate grammar. If you can get syntax highlighting to work for your favorite language in any one of them, try to find its grammar and load it in Shiki to syntax highlight it:

-
const shiki = require('shiki')
+
const shiki = require('shiki')
 
 shiki.getHighlighter({
   theme: 'nord',
@@ -88,7 +88,7 @@ 

shiki

Over 100 programming languages are supported out of the box, including a traditional Chinese one, 文言:

Shiki can load any VS Code themes. Just change this line:

-
shiki.getHighlighter({
+
shiki.getHighlighter({
   theme: 'material-theme-palenight'
 })
 
@@ -96,7 +96,7 @@

shiki

You can find all bundled themes in shiki-themes, and use them like:

-
shiki.getHighlighter({
+
shiki.getHighlighter({
   // 'dark-plus'   | 'light-plus'     => for the classic VS Code feel
   // 'github-dark' | 'github-light'   => for the GitHub feel
   // 'material-theme-*'               => for the materialists
@@ -107,10 +107,10 @@ 

shiki

But really, any VS Code theme will do. Here's anotherglitchinthematrix/monochrome:

Embedded language like Vue works great, too:

-
<template>
+
<template>
   <div id="app">
     <h1>My Todo App!</h1>
-    <TodoList/>
+    <TodoList/>
   </div>
 </template>
 
@@ -124,7 +124,7 @@ 

shiki

} </script> -<style lang="scss"> +<style lang="scss"> #app { max-width: 400px; margin: 0 auto; @@ -147,7 +147,7 @@

shiki

and use the full arsenal of vector editing tools to enhance your code presentation:

Editing In Figma

You can also build custom renderers to generate anything — a different HTML structure, SVG, or even images:

-
const shiki = require('shiki')
+
const shiki = require('shiki')
 
 shiki.getHighlighter({
   theme: 'nord'
diff --git a/packages/site/mono.html b/packages/site/mono.html
index 73d54eba7..4812a7fae 100644
--- a/packages/site/mono.html
+++ b/packages/site/mono.html
@@ -1,6 +1,6 @@
-
const shiki = require('shiki')
+
const shiki = require('shiki')
 
 shiki.getHighlighter({
-  theme: JSON.parse(fs.readFileSync('./monochrome-dark-subtle.json', 'utf-8'))
+  theme: JSON.parse(fs.readFileSync('./monochrome-dark-subtle.json', 'utf-8'))
 })
 
diff --git a/packages/site/package.json b/packages/site/package.json index 38e5b167d..de4f58e91 100644 --- a/packages/site/package.json +++ b/packages/site/package.json @@ -3,9 +3,9 @@ "version": "0.13.0", "private": true, "devDependencies": { - "@types/node": "^18.11.15", + "@types/node": "^18.11.17", "markdown-it": "^13.0.1", - "playwright": "^1.28.1", + "playwright": "^1.29.0", "shiki": "^0.13.0", "shiki-renderer-svg": "^0.13.0" }, diff --git a/packages/site/palenight.html b/packages/site/palenight.html index b36f45c90..031f3bd70 100644 --- a/packages/site/palenight.html +++ b/packages/site/palenight.html @@ -1,4 +1,4 @@ -
import * as React from 'react';
+
import * as React from 'react';
 import './App.css';
 import Hello from './components/Hello';
 
diff --git a/packages/site/rockstar.html b/packages/site/rockstar.html
index 7316f1c5f..a7a32274b 100644
--- a/packages/site/rockstar.html
+++ b/packages/site/rockstar.html
@@ -1,4 +1,4 @@
-
Midnight takes your heart and your soul
+
Midnight takes your heart and your soul
 While your heart is as high as your soul
 Put your heart without your soul into your heart
 
diff --git a/packages/site/svg.svg b/packages/site/svg.svg
index 5939af28b..cbe9f1b7a 100644
--- a/packages/site/svg.svg
+++ b/packages/site/svg.svg
@@ -1,5 +1,5 @@
 
-
+
 const fs = require('fs')
 
 
diff --git "a/packages/site/\346\226\207\350\250\200.html" "b/packages/site/\346\226\207\350\250\200.html"
index fb409ecfc..9c657bda8 100644
--- "a/packages/site/\346\226\207\350\250\200.html"
+++ "b/packages/site/\346\226\207\350\250\200.html"
@@ -1,4 +1,4 @@
-
吾有「「春日宴。」」書之
+
吾有「「春日宴。」」書之
 有數名之曰「酒數」
 
 恆為是「酒數」等於者乃止也
diff --git a/playwright.config.ts b/playwright.config.ts
new file mode 100644
index 000000000..4410834fc
--- /dev/null
+++ b/playwright.config.ts
@@ -0,0 +1,43 @@
+import type { PlaywrightTestConfig } from '@playwright/test'
+import { devices } from '@playwright/test'
+
+const PORT = +process.env.PORT || 3000
+const SERVER = `http://127.0.0.1:${PORT}`
+
+const config: PlaywrightTestConfig = {
+  timeout: 15 * 1000,
+  expect: {
+    timeout: 5000
+  },
+  globalSetup: './scripts/e2e/setup.mjs',
+  globalTeardown: './scripts/e2e/teardown.mjs',
+  snapshotPathTemplate: './packages/shiki/src/__tests__/__screenshots__{/projectName}/{arg}{ext}',
+  fullyParallel: true,
+  forbidOnly: !!process.env.CI,
+  retries: process.env.CI ? 2 : 0,
+  workers: process.env.CI ? 1 : undefined,
+  reporter: process.env.CI ? [['github'], ['html']] : 'html',
+  use: {
+    baseURL: SERVER,
+    trace: 'on-first-retry',
+    headless: true
+  },
+  projects: [
+    {
+      name: 'shiki-browser',
+      testMatch: /packages\/shiki\/src\/__tests__\/e2e.browser.spec.ts/,
+      use: {
+        ...devices['Desktop Chrome']
+      }
+    },
+    {
+      name: 'shiki-cdn',
+      testMatch: /packages\/shiki\/src\/__tests__\/e2e.cdn.spec.ts/,
+      use: {
+        ...devices['Desktop Chrome']
+      }
+    }
+  ]
+}
+
+export default config
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 096929a56..3e5930544 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,7 +4,8 @@ importers:
 
   .:
     specifiers:
-      '@rollup/plugin-commonjs': ^23.0.7
+      '@playwright/test': ^1.29.0
+      '@rollup/plugin-commonjs': ^24.0.0
       '@rollup/plugin-node-resolve': ^15.0.1
       '@rollup/plugin-replace': ^5.0.2
       '@rollup/plugin-terser': ^0.2.1
@@ -17,7 +18,7 @@ importers:
       chalk: ^5.2.0
       cross-env: ^7.0.3
       cson: ^7.20.0
-      esbuild: ^0.16.7
+      esbuild: ^0.16.10
       esno: ^0.16.3
       fast-plist: ^0.1.3
       fs-extra: ^11.1.0
@@ -31,18 +32,20 @@ importers:
       rollup-plugin-copy: ^3.4.0
       rollup-plugin-dts: ^5.1.1
       rollup-plugin-esbuild: ^5.0.0
+      superstatic: ^9.0.0
       ts-jest: ^29.0.5
       tsup: ^6.5.0
       typescript: ^4.9.4
       unzipper: ^0.10.11
       yorkie: ^2.0.0
     dependencies:
-      esbuild: 0.16.7
+      esbuild: 0.16.17
     devDependencies:
-      '@rollup/plugin-commonjs': 23.0.7_rollup@3.11.0
-      '@rollup/plugin-node-resolve': 15.0.1_rollup@3.11.0
-      '@rollup/plugin-replace': 5.0.2_rollup@3.11.0
-      '@rollup/plugin-terser': 0.2.1_rollup@3.11.0
+      '@playwright/test': 1.30.0
+      '@rollup/plugin-commonjs': 24.0.1_rollup@3.12.0
+      '@rollup/plugin-node-resolve': 15.0.1_rollup@3.12.0
+      '@rollup/plugin-replace': 5.0.2_rollup@3.12.0
+      '@rollup/plugin-terser': 0.2.1_rollup@3.12.0
       '@types/cson': 7.20.1
       '@types/fs-extra': 9.0.13
       '@types/jest': 29.4.0
@@ -61,11 +64,12 @@ importers:
       lint-staged: 13.1.0
       lodash.kebabcase: 4.1.1
       prettier: 2.8.3
-      rollup: 3.11.0
+      rollup: 3.12.0
       rollup-plugin-copy: 3.4.0
-      rollup-plugin-dts: 5.1.1_yjrzni4zyr7xhg3xsvmmijxnvu
-      rollup-plugin-esbuild: 5.0.0_h6jqhw2rq3gbm5ffzodjfjev5e
-      ts-jest: 29.0.5_eks76w3tabv3bn6sckcjgzhh44
+      rollup-plugin-dts: 5.1.1_tkwgik6422u3whqaozmypsnvni
+      rollup-plugin-esbuild: 5.0.0_7k6ev2cyiz7vefgkiohpkhn6r4
+      superstatic: 9.0.2
+      ts-jest: 29.0.5_fcfrzhucaalut4icxzmgymelre
       tsup: 6.5.0_typescript@4.9.4
       typescript: 4.9.4
       unzipper: 0.10.11
@@ -73,29 +77,29 @@ importers:
 
   packages/renderer-path:
     specifiers:
-      '@types/node': ^18.11.15
+      '@types/node': ^18.11.17
       '@types/opentype.js': ^1.3.4
       opentype.js: ^1.3.4
       shiki: ^0.13.0
     devDependencies:
-      '@types/node': 18.11.15
+      '@types/node': 18.11.18
       '@types/opentype.js': 1.3.4
       opentype.js: 1.3.4
       shiki: link:../shiki
 
   packages/renderer-svg:
     specifiers:
-      '@types/node': ^18.11.15
-      playwright: ^1.28.1
+      '@types/node': ^18.11.17
+      playwright: ^1.29.0
       shiki: ^0.13.0
     devDependencies:
-      '@types/node': 18.11.15
-      playwright: 1.28.1
+      '@types/node': 18.11.18
+      playwright: 1.30.0
       shiki: link:../shiki
 
   packages/shiki:
     specifiers:
-      '@types/node': ^18.11.15
+      '@types/node': ^18.11.17
       ansi-sequence-parser: ^1.1.0
       jsonc-parser: ^3.2.0
       vscode-oniguruma: ^1.7.0
@@ -106,19 +110,19 @@ importers:
       vscode-oniguruma: 1.7.0
       vscode-textmate: 8.0.0
     devDependencies:
-      '@types/node': 18.11.15
+      '@types/node': 18.11.18
 
   packages/site:
     specifiers:
-      '@types/node': ^18.11.15
+      '@types/node': ^18.11.17
       markdown-it: ^13.0.1
-      playwright: ^1.28.1
+      playwright: ^1.29.0
       shiki: ^0.13.0
       shiki-renderer-svg: ^0.13.0
     devDependencies:
-      '@types/node': 18.11.15
+      '@types/node': 18.11.18
       markdown-it: 13.0.1
-      playwright: 1.28.1
+      playwright: 1.30.0
       shiki: link:../shiki
       shiki-renderer-svg: link:../renderer-svg
 
@@ -145,8 +149,8 @@ packages:
       '@babel/highlight': 7.18.6
     dev: true
 
-  /@babel/compat-data/7.20.10:
-    resolution: {integrity: sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==}
+  /@babel/compat-data/7.20.14:
+    resolution: {integrity: sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw==}
     engines: {node: '>=6.9.0'}
     dev: true
 
@@ -156,7 +160,7 @@ packages:
     dependencies:
       '@ampproject/remapping': 2.2.0
       '@babel/code-frame': 7.18.6
-      '@babel/generator': 7.20.7
+      '@babel/generator': 7.20.14
       '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.12
       '@babel/helper-module-transforms': 7.20.11
       '@babel/helpers': 7.20.13
@@ -173,8 +177,8 @@ packages:
       - supports-color
     dev: true
 
-  /@babel/generator/7.20.7:
-    resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==}
+  /@babel/generator/7.20.14:
+    resolution: {integrity: sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/types': 7.20.7
@@ -188,7 +192,7 @@ packages:
     peerDependencies:
       '@babel/core': ^7.0.0
     dependencies:
-      '@babel/compat-data': 7.20.10
+      '@babel/compat-data': 7.20.14
       '@babel/core': 7.20.12
       '@babel/helper-validator-option': 7.18.6
       browserslist: 4.21.4
@@ -444,7 +448,7 @@ packages:
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/code-frame': 7.18.6
-      '@babel/generator': 7.20.7
+      '@babel/generator': 7.20.14
       '@babel/helper-environment-visitor': 7.18.9
       '@babel/helper-function-name': 7.19.0
       '@babel/helper-hoist-variables': 7.18.6
@@ -500,80 +504,80 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/android-arm/0.16.7:
-    resolution: {integrity: sha512-yhzDbiVcmq6T1/XEvdcJIVcXHdLjDJ5cQ0Dp9R9p9ERMBTeO1dR5tc8YYv8zwDeBw1xZm+Eo3MRo8cwclhBS0g==}
+  /@esbuild/android-arm/0.16.17:
+    resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [android]
     requiresBuild: true
     optional: true
 
-  /@esbuild/android-arm64/0.16.7:
-    resolution: {integrity: sha512-tYFw0lBJSEvLoGzzYh1kXuzoX1iPkbOk3O29VqzQb0HbOy7t/yw1hGkvwoJhXHwzQUPsShyYcTgRf6bDBcfnTw==}
+  /@esbuild/android-arm64/0.16.17:
+    resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [android]
     requiresBuild: true
     optional: true
 
-  /@esbuild/android-x64/0.16.7:
-    resolution: {integrity: sha512-3P2OuTxwAtM3k/yEWTNUJRjMPG1ce8rXs51GTtvEC5z1j8fC1plHeVVczdeHECU7aM2/Buc0MwZ6ciM/zysnWg==}
+  /@esbuild/android-x64/0.16.17:
+    resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [android]
     requiresBuild: true
     optional: true
 
-  /@esbuild/darwin-arm64/0.16.7:
-    resolution: {integrity: sha512-VUb9GK23z8jkosHU9yJNUgQpsfJn+7ZyBm6adi2Ec5/U241eR1tAn82QicnUzaFDaffeixiHwikjmnec/YXEZg==}
+  /@esbuild/darwin-arm64/0.16.17:
+    resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [darwin]
     requiresBuild: true
     optional: true
 
-  /@esbuild/darwin-x64/0.16.7:
-    resolution: {integrity: sha512-duterlv3tit3HI9vhzMWnSVaB1B6YsXpFq1Ntd6Fou82BB1l4tucYy3FI9dHv3tvtDuS0NiGf/k6XsdBqPZ01w==}
+  /@esbuild/darwin-x64/0.16.17:
+    resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [darwin]
     requiresBuild: true
     optional: true
 
-  /@esbuild/freebsd-arm64/0.16.7:
-    resolution: {integrity: sha512-9kkycpBFes/vhi7B7o0cf+q2WdJi+EpVzpVTqtWFNiutARWDFFLcB93J8PR1cG228sucsl3B+7Ts27izE6qiaQ==}
+  /@esbuild/freebsd-arm64/0.16.17:
+    resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [freebsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/freebsd-x64/0.16.7:
-    resolution: {integrity: sha512-5Ahf6jzWXJ4J2uh9dpy5DKOO+PeRUE/9DMys6VuYfwgQzd6n5+pVFm58L2Z2gRe611RX6SdydnNaiIKM3svY7g==}
+  /@esbuild/freebsd-x64/0.16.17:
+    resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [freebsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-arm/0.16.7:
-    resolution: {integrity: sha512-QqJnyCfu5OF78Olt7JJSZ7OSv/B4Hf+ZJWp4kkq9xwMsgu7yWq3crIic8gGOpDYTqVKKMDAVDgRXy5Wd/nWZyQ==}
+  /@esbuild/linux-arm/0.16.17:
+    resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-arm64/0.16.7:
-    resolution: {integrity: sha512-2wv0xYDskk2+MzIm/AEprDip39a23Chptc4mL7hsHg26P0gD8RUhzmDu0KCH2vMThUI1sChXXoK9uH0KYQKaDg==}
+  /@esbuild/linux-arm64/0.16.17:
+    resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-ia32/0.16.7:
-    resolution: {integrity: sha512-APVYbEilKbD5ptmKdnIcXej2/+GdV65TfTjxR2Uk8t1EsOk49t6HapZW6DS/Bwlvh5hDwtLapdSumIVNGxgqLg==}
+  /@esbuild/linux-ia32/0.16.17:
+    resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [linux]
@@ -589,96 +593,96 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-loong64/0.16.7:
-    resolution: {integrity: sha512-5wPUAGclplQrAW7EFr3F84Y/d++7G0KykohaF4p54+iNWhUnMVU8Bh2sxiEOXUy4zKIdpHByMgJ5/Ko6QhtTUw==}
+  /@esbuild/linux-loong64/0.16.17:
+    resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==}
     engines: {node: '>=12'}
     cpu: [loong64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-mips64el/0.16.7:
-    resolution: {integrity: sha512-hxzlXtWF6yWfkE/SMTscNiVqLOAn7fOuIF3q/kiZaXxftz1DhZW/HpnTmTTWrzrS7zJWQxHHT4QSxyAj33COmA==}
+  /@esbuild/linux-mips64el/0.16.17:
+    resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==}
     engines: {node: '>=12'}
     cpu: [mips64el]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-ppc64/0.16.7:
-    resolution: {integrity: sha512-WM83Dac0LdXty5xPhlOuCD5Egfk1xLND/oRLYeB7Jb/tY4kzFSDgLlq91wYbHua/s03tQGA9iXvyjgymMw62Vw==}
+  /@esbuild/linux-ppc64/0.16.17:
+    resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==}
     engines: {node: '>=12'}
     cpu: [ppc64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-riscv64/0.16.7:
-    resolution: {integrity: sha512-3nkNnNg4Ax6MS/l8O8Ynq2lGEVJYyJ2EoY3PHjNJ4PuZ80EYLMrFTFZ4L/Hc16AxgtXKwmNP9TM0YKNiBzBiJQ==}
+  /@esbuild/linux-riscv64/0.16.17:
+    resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==}
     engines: {node: '>=12'}
     cpu: [riscv64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-s390x/0.16.7:
-    resolution: {integrity: sha512-3SA/2VJuv0o1uD7zuqxEP+RrAyRxnkGddq0bwHQ98v1KNlzXD/JvxwTO3T6GM5RH6JUd29RTVQTOJfyzMkkppA==}
+  /@esbuild/linux-s390x/0.16.17:
+    resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==}
     engines: {node: '>=12'}
     cpu: [s390x]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-x64/0.16.7:
-    resolution: {integrity: sha512-xi/tbqCqvPIzU+zJVyrpz12xqciTAPMi2fXEWGnapZymoGhuL2GIWIRXg4O2v5BXaYA5TSaiKYE14L0QhUTuQg==}
+  /@esbuild/linux-x64/0.16.17:
+    resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/netbsd-x64/0.16.7:
-    resolution: {integrity: sha512-NUsYbq3B+JdNKn8SXkItFvdes9qTwEoS3aLALtiWciW/ystiCKM20Fgv9XQBOXfhUHyh5CLEeZDXzLOrwBXuCQ==}
+  /@esbuild/netbsd-x64/0.16.17:
+    resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [netbsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/openbsd-x64/0.16.7:
-    resolution: {integrity: sha512-qjwzsgeve9I8Tbsko2FEkdSk2iiezuNGFgipQxY/736NePXDaDZRodIejYGWOlbYXugdxb0nif5yvypH6lKBmA==}
+  /@esbuild/openbsd-x64/0.16.17:
+    resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [openbsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/sunos-x64/0.16.7:
-    resolution: {integrity: sha512-mFWDz4RoBTzPphTCkM7Kc7Qpa0o/Z01acajR+Ai7LdfKgcP/C6jYOaKwv7nKzD0+MjOT20j7You9g4ozYy1dKQ==}
+  /@esbuild/sunos-x64/0.16.17:
+    resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [sunos]
     requiresBuild: true
     optional: true
 
-  /@esbuild/win32-arm64/0.16.7:
-    resolution: {integrity: sha512-m39UmX19RvEIuC8sYZ0M+eQtdXw4IePDSZ78ZQmYyFaXY9krq4YzQCK2XWIJomNLtg4q+W5aXr8bW3AbqWNoVg==}
+  /@esbuild/win32-arm64/0.16.17:
+    resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [win32]
     requiresBuild: true
     optional: true
 
-  /@esbuild/win32-ia32/0.16.7:
-    resolution: {integrity: sha512-1cbzSEZA1fANwmT6rjJ4G1qQXHxCxGIcNYFYR9ctI82/prT38lnwSRZ0i5p/MVXksw9eMlHlet6pGu2/qkXFCg==}
+  /@esbuild/win32-ia32/0.16.17:
+    resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [win32]
     requiresBuild: true
     optional: true
 
-  /@esbuild/win32-x64/0.16.7:
-    resolution: {integrity: sha512-QaQ8IH0JLacfGf5cf0HCCPnQuCTd/dAI257vXBgb/cccKGbH/6pVtI1gwhdAQ0Y48QSpTIFrh9etVyNdZY+zzw==}
+  /@esbuild/win32-x64/0.16.17:
+    resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [win32]
@@ -1491,7 +1495,7 @@ packages:
       npmlog: 6.0.2
     dev: true
 
-  /@lerna/publish/6.4.1_nx@15.6.2+typescript@4.9.4:
+  /@lerna/publish/6.4.1_nx@15.6.3+typescript@4.9.4:
     resolution: {integrity: sha512-/D/AECpw2VNMa1Nh4g29ddYKRIqygEV1ftV8PYXVlHpqWN7VaKrcbRU6pn0ldgpFlMyPtESfv1zS32F5CQ944w==}
     engines: {node: ^14.15.0 || >=16.0.0}
     dependencies:
@@ -1513,7 +1517,7 @@ packages:
       '@lerna/run-lifecycle': 6.4.1
       '@lerna/run-topologically': 6.4.1
       '@lerna/validation-error': 6.4.1
-      '@lerna/version': 6.4.1_nx@15.6.2+typescript@4.9.4
+      '@lerna/version': 6.4.1_nx@15.6.3+typescript@4.9.4
       fs-extra: 9.1.0
       libnpmaccess: 6.0.4
       npm-package-arg: 8.1.1
@@ -1598,7 +1602,7 @@ packages:
       '@lerna/timer': 6.4.1
       '@lerna/validation-error': 6.4.1
       fs-extra: 9.1.0
-      nx: 15.6.2
+      nx: 15.6.3
       p-map: 4.0.0
     transitivePeerDependencies:
       - '@swc-node/register'
@@ -1650,7 +1654,7 @@ packages:
       npmlog: 6.0.2
     dev: true
 
-  /@lerna/version/6.4.1_nx@15.6.2+typescript@4.9.4:
+  /@lerna/version/6.4.1_nx@15.6.3+typescript@4.9.4:
     resolution: {integrity: sha512-1/krPq0PtEqDXtaaZsVuKev9pXJCkNC1vOo2qCcn6PBkODw/QTAvGcUi0I+BM2c//pdxge9/gfmbDo1lC8RtAQ==}
     engines: {node: ^14.15.0 || >=16.0.0}
     dependencies:
@@ -1668,7 +1672,7 @@ packages:
       '@lerna/run-topologically': 6.4.1
       '@lerna/temp-write': 6.4.1
       '@lerna/validation-error': 6.4.1
-      '@nrwl/devkit': 15.6.2_nx@15.6.2+typescript@4.9.4
+      '@nrwl/devkit': 15.6.3_nx@15.6.3+typescript@4.9.4
       chalk: 4.1.2
       dedent: 0.7.0
       load-json-file: 6.2.0
@@ -1865,36 +1869,36 @@ packages:
       - supports-color
     dev: true
 
-  /@nrwl/cli/15.6.2:
-    resolution: {integrity: sha512-7U9hYVTwXqPZSqRxYTDO+wCudASuknqTAY6151RrpT4HDK5BpkMxC96HW/wvhrzaLf+7dLHAimr2b+vR2xnqRA==}
+  /@nrwl/cli/15.6.3:
+    resolution: {integrity: sha512-K4E0spofThZXMnhA6R8hkUTdfqmwSnUE2+DlD5Y3jqsvKTAgwF5U41IFkEouFZCf+dWjy0RA20bWoX48EVFtmQ==}
     dependencies:
-      nx: 15.6.2
+      nx: 15.6.3
     transitivePeerDependencies:
       - '@swc-node/register'
       - '@swc/core'
       - debug
     dev: true
 
-  /@nrwl/devkit/15.6.2_nx@15.6.2+typescript@4.9.4:
-    resolution: {integrity: sha512-RcPwjr1btr16wz/ZTnLeKMLu4zATWoh5E94qrFxw3n8hXbC5cIW0Hs/D3ho7cuJQCtQmItTD21M7akjvgHsniA==}
+  /@nrwl/devkit/15.6.3_nx@15.6.3+typescript@4.9.4:
+    resolution: {integrity: sha512-/JDvdzNxUM+C1PCZPCrvmFx+OfywqZdOq1GS9QR8C0VctTLG4D/SGSFD88O1SAdcbH/f1mMiBGfEYZYd23fghQ==}
     peerDependencies:
       nx: '>= 14 <= 16'
     dependencies:
       '@phenomnomnominal/tsquery': 4.1.1_typescript@4.9.4
       ejs: 3.1.8
       ignore: 5.2.4
-      nx: 15.6.2
+      nx: 15.6.3
       semver: 7.3.4
       tslib: 2.5.0
     transitivePeerDependencies:
       - typescript
     dev: true
 
-  /@nrwl/tao/15.6.2:
-    resolution: {integrity: sha512-jG8Csd43uyFf1XUc02k1XoK89n3FsvXM9EXdFadKLbiw5/7c0dZ0AYK8+JFgRpk67/7T0qaxtw8YlKdkuf/uJg==}
+  /@nrwl/tao/15.6.3:
+    resolution: {integrity: sha512-bDZbPIbU5Mf2BvX0q8GjPxrm1WkYyfW+gp7mLuuJth2sEpZiCr47mSwuGko/y4CKXvIX46VQcAS0pKQMKugXsg==}
     hasBin: true
     dependencies:
-      nx: 15.6.2
+      nx: 15.6.3
     transitivePeerDependencies:
       - '@swc-node/register'
       - '@swc/core'
@@ -2039,8 +2043,32 @@ packages:
       typescript: 4.9.4
     dev: true
 
-  /@rollup/plugin-commonjs/23.0.7_rollup@3.11.0:
-    resolution: {integrity: sha512-hsSD5Qzyuat/swzrExGG5l7EuIlPhwTsT7KwKbSCQzIcJWjRxiimi/0tyMYY2bByitNb3i1p+6JWEDGa0NvT0Q==}
+  /@playwright/test/1.30.0:
+    resolution: {integrity: sha512-SVxkQw1xvn/Wk/EvBnqWIq6NLo1AppwbYOjNLmyU0R1RoQ3rLEBtmjTnElcnz8VEtn11fptj1ECxK0tgURhajw==}
+    engines: {node: '>=14'}
+    hasBin: true
+    dependencies:
+      '@types/node': 18.11.18
+      playwright-core: 1.30.0
+    dev: true
+
+  /@pnpm/network.ca-file/1.0.2:
+    resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==}
+    engines: {node: '>=12.22.0'}
+    dependencies:
+      graceful-fs: 4.2.10
+    dev: true
+
+  /@pnpm/npm-conf/1.0.5:
+    resolution: {integrity: sha512-hD8ml183638O3R6/Txrh0L8VzGOrFXgRtRDG4qQC4tONdZ5Z1M+tlUUDUvrjYdmK6G+JTBTeaCLMna11cXzi8A==}
+    engines: {node: '>=12'}
+    dependencies:
+      '@pnpm/network.ca-file': 1.0.2
+      config-chain: 1.1.13
+    dev: true
+
+  /@rollup/plugin-commonjs/24.0.1_rollup@3.12.0:
+    resolution: {integrity: sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
       rollup: ^2.68.0||^3.0.0
@@ -2048,16 +2076,16 @@ packages:
       rollup:
         optional: true
     dependencies:
-      '@rollup/pluginutils': 5.0.2_rollup@3.11.0
+      '@rollup/pluginutils': 5.0.2_rollup@3.12.0
       commondir: 1.0.1
       estree-walker: 2.0.2
       glob: 8.1.0
       is-reference: 1.2.1
       magic-string: 0.27.0
-      rollup: 3.11.0
+      rollup: 3.12.0
     dev: true
 
-  /@rollup/plugin-node-resolve/15.0.1_rollup@3.11.0:
+  /@rollup/plugin-node-resolve/15.0.1_rollup@3.12.0:
     resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
@@ -2066,16 +2094,16 @@ packages:
       rollup:
         optional: true
     dependencies:
-      '@rollup/pluginutils': 5.0.2_rollup@3.11.0
+      '@rollup/pluginutils': 5.0.2_rollup@3.12.0
       '@types/resolve': 1.20.2
       deepmerge: 4.2.2
       is-builtin-module: 3.2.0
       is-module: 1.0.0
       resolve: 1.22.1
-      rollup: 3.11.0
+      rollup: 3.12.0
     dev: true
 
-  /@rollup/plugin-replace/5.0.2_rollup@3.11.0:
+  /@rollup/plugin-replace/5.0.2_rollup@3.12.0:
     resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
@@ -2084,12 +2112,12 @@ packages:
       rollup:
         optional: true
     dependencies:
-      '@rollup/pluginutils': 5.0.2_rollup@3.11.0
+      '@rollup/pluginutils': 5.0.2_rollup@3.12.0
       magic-string: 0.27.0
-      rollup: 3.11.0
+      rollup: 3.12.0
     dev: true
 
-  /@rollup/plugin-terser/0.2.1_rollup@3.11.0:
+  /@rollup/plugin-terser/0.2.1_rollup@3.12.0:
     resolution: {integrity: sha512-hV52c8Oo6/cXZZxVVoRNBb4zh+EKSHS4I1sedWV5pf0O+hTLSkrf6w86/V0AZutYtwBguB6HLKwz89WDBfwGOA==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
@@ -2098,13 +2126,13 @@ packages:
       rollup:
         optional: true
     dependencies:
-      rollup: 3.11.0
+      rollup: 3.12.0
       serialize-javascript: 6.0.1
       smob: 0.0.6
       terser: 5.16.1
     dev: true
 
-  /@rollup/pluginutils/5.0.2_rollup@3.11.0:
+  /@rollup/pluginutils/5.0.2_rollup@3.12.0:
     resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
@@ -2116,7 +2144,7 @@ packages:
       '@types/estree': 1.0.0
       estree-walker: 2.0.2
       picomatch: 2.3.1
-      rollup: 3.11.0
+      rollup: 3.12.0
     dev: true
 
   /@sinclair/typebox/0.25.21:
@@ -2241,10 +2269,6 @@ packages:
     resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
     dev: true
 
-  /@types/node/18.11.15:
-    resolution: {integrity: sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw==}
-    dev: true
-
   /@types/node/18.11.18:
     resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==}
     dev: true
@@ -2320,6 +2344,14 @@ packages:
     resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
     dev: true
 
+  /accepts/1.3.8:
+    resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
+    engines: {node: '>= 0.6'}
+    dependencies:
+      mime-types: 2.1.35
+      negotiator: 0.6.3
+    dev: true
+
   /acorn/8.8.2:
     resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
     engines: {node: '>=0.4.0'}
@@ -2358,6 +2390,12 @@ packages:
       indent-string: 4.0.0
     dev: true
 
+  /ansi-align/3.0.1:
+    resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
+    dependencies:
+      string-width: 4.2.3
+    dev: true
+
   /ansi-colors/4.1.3:
     resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
     engines: {node: '>=6'}
@@ -2447,6 +2485,10 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
+  /array-flatten/3.0.0:
+    resolution: {integrity: sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==}
+    dev: true
+
   /array-ify/1.0.0:
     resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==}
     dev: true
@@ -2466,6 +2508,10 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
+  /as-array/2.0.0:
+    resolution: {integrity: sha512-1Sd1LrodN0XYxYeZcN1J4xYZvmvTwD5tDWaPUGPIzH1mFsmzsPnVtd2exWhecMjtZk/wYWjNZJiD3b1SLCeJqg==}
+    dev: true
+
   /asap/2.0.6:
     resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
     dev: true
@@ -2578,6 +2624,17 @@ packages:
     resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
     dev: true
 
+  /basic-auth-connect/1.0.0:
+    resolution: {integrity: sha512-kiV+/DTgVro4aZifY/hwRwALBISViL5NP4aReaR2EVJEObpbUBHIkdJh/YpcoEiYt7nBodZ6U2ajZeZvSxUCCg==}
+    dev: true
+
+  /basic-auth/2.0.1:
+    resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==}
+    engines: {node: '>= 0.8'}
+    dependencies:
+      safe-buffer: 5.1.2
+    dev: true
+
   /before-after-hook/2.2.3:
     resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
     dev: true
@@ -2623,6 +2680,20 @@ packages:
     resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==}
     dev: true
 
+  /boxen/5.1.2:
+    resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      ansi-align: 3.0.1
+      camelcase: 6.3.0
+      chalk: 4.1.2
+      cli-boxes: 2.2.1
+      string-width: 4.2.3
+      type-fest: 0.20.2
+      widest-line: 3.1.0
+      wrap-ansi: 7.0.0
+    dev: true
+
   /brace-expansion/1.1.11:
     resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
     dependencies:
@@ -2718,6 +2789,11 @@ packages:
     engines: {node: '>=10'}
     dev: true
 
+  /bytes/3.0.0:
+    resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
   /cac/6.7.14:
     resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
     engines: {node: '>=8'}
@@ -2856,6 +2932,11 @@ packages:
     engines: {node: '>=6'}
     dev: true
 
+  /cli-boxes/2.2.1:
+    resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==}
+    engines: {node: '>=6'}
+    dev: true
+
   /cli-cursor/3.1.0:
     resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
     engines: {node: '>=8'}
@@ -3025,6 +3106,28 @@ packages:
       dot-prop: 5.3.0
     dev: true
 
+  /compressible/2.0.18:
+    resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
+    engines: {node: '>= 0.6'}
+    dependencies:
+      mime-db: 1.52.0
+    dev: true
+
+  /compression/1.7.4:
+    resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      accepts: 1.3.8
+      bytes: 3.0.0
+      compressible: 2.0.18
+      debug: 2.6.9
+      on-headers: 1.0.2
+      safe-buffer: 5.1.2
+      vary: 1.1.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /concat-map/0.0.1:
     resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
     dev: true
@@ -3046,6 +3149,30 @@ packages:
       proto-list: 1.2.4
     dev: true
 
+  /configstore/5.0.1:
+    resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==}
+    engines: {node: '>=8'}
+    dependencies:
+      dot-prop: 5.3.0
+      graceful-fs: 4.2.10
+      make-dir: 3.1.0
+      unique-string: 2.0.0
+      write-file-atomic: 3.0.3
+      xdg-basedir: 4.0.0
+    dev: true
+
+  /connect/3.7.0:
+    resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==}
+    engines: {node: '>= 0.10.0'}
+    dependencies:
+      debug: 2.6.9
+      finalhandler: 1.1.2
+      parseurl: 1.3.3
+      utils-merge: 1.0.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /console-control-strings/1.1.0:
     resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
     dev: true
@@ -3183,6 +3310,11 @@ packages:
       which: 2.0.2
     dev: true
 
+  /crypto-random-string/2.0.0:
+    resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
+    engines: {node: '>=8'}
+    dev: true
+
   /cson-parser/4.0.9:
     resolution: {integrity: sha512-I79SAcCYquWnEfXYj8hBqOOWKj6eH6zX1hhX3yqmS4K3bYp7jME3UFpHPzu3rUew0oyfc0s8T6IlWGXRAheHag==}
     engines: {node: '>=10.13'}
@@ -3210,6 +3342,17 @@ packages:
     resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==}
     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/4.3.4:
     resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
     engines: {node: '>=6.0'}
@@ -3243,6 +3386,11 @@ packages:
     resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
     dev: true
 
+  /deep-extend/0.6.0:
+    resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+    engines: {node: '>=4.0.0'}
+    dev: true
+
   /deepmerge/4.2.2:
     resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
     engines: {node: '>=0.10.0'}
@@ -3273,10 +3421,20 @@ packages:
     engines: {node: '>= 0.6'}
     dev: true
 
+  /depd/2.0.0:
+    resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
   /deprecation/2.3.1:
     resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==}
     dev: true
 
+  /destroy/1.2.0:
+    resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
+    engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+    dev: true
+
   /detect-indent/5.0.0:
     resolution: {integrity: sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==}
     engines: {node: '>=4'}
@@ -3351,6 +3509,10 @@ packages:
     resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
     dev: true
 
+  /ee-first/1.1.1:
+    resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+    dev: true
+
   /ejs/3.1.8:
     resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==}
     engines: {node: '>=0.10.0'}
@@ -3376,6 +3538,11 @@ packages:
     resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
     dev: true
 
+  /encodeurl/1.0.2:
+    resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
   /encoding/0.1.13:
     resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
     requiresBuild: true
@@ -3637,40 +3804,49 @@ packages:
       esbuild-windows-arm64: 0.15.18
     dev: true
 
-  /esbuild/0.16.7:
-    resolution: {integrity: sha512-P6OBFYFSQOGzfApqCeYKqfKRRbCIRsdppTXFo4aAvtiW3o8TTyiIplBvHJI171saPAiy3WlawJHCveJVIOIx1A==}
+  /esbuild/0.16.17:
+    resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==}
     engines: {node: '>=12'}
     hasBin: true
     requiresBuild: true
     optionalDependencies:
-      '@esbuild/android-arm': 0.16.7
-      '@esbuild/android-arm64': 0.16.7
-      '@esbuild/android-x64': 0.16.7
-      '@esbuild/darwin-arm64': 0.16.7
-      '@esbuild/darwin-x64': 0.16.7
-      '@esbuild/freebsd-arm64': 0.16.7
-      '@esbuild/freebsd-x64': 0.16.7
-      '@esbuild/linux-arm': 0.16.7
-      '@esbuild/linux-arm64': 0.16.7
-      '@esbuild/linux-ia32': 0.16.7
-      '@esbuild/linux-loong64': 0.16.7
-      '@esbuild/linux-mips64el': 0.16.7
-      '@esbuild/linux-ppc64': 0.16.7
-      '@esbuild/linux-riscv64': 0.16.7
-      '@esbuild/linux-s390x': 0.16.7
-      '@esbuild/linux-x64': 0.16.7
-      '@esbuild/netbsd-x64': 0.16.7
-      '@esbuild/openbsd-x64': 0.16.7
-      '@esbuild/sunos-x64': 0.16.7
-      '@esbuild/win32-arm64': 0.16.7
-      '@esbuild/win32-ia32': 0.16.7
-      '@esbuild/win32-x64': 0.16.7
+      '@esbuild/android-arm': 0.16.17
+      '@esbuild/android-arm64': 0.16.17
+      '@esbuild/android-x64': 0.16.17
+      '@esbuild/darwin-arm64': 0.16.17
+      '@esbuild/darwin-x64': 0.16.17
+      '@esbuild/freebsd-arm64': 0.16.17
+      '@esbuild/freebsd-x64': 0.16.17
+      '@esbuild/linux-arm': 0.16.17
+      '@esbuild/linux-arm64': 0.16.17
+      '@esbuild/linux-ia32': 0.16.17
+      '@esbuild/linux-loong64': 0.16.17
+      '@esbuild/linux-mips64el': 0.16.17
+      '@esbuild/linux-ppc64': 0.16.17
+      '@esbuild/linux-riscv64': 0.16.17
+      '@esbuild/linux-s390x': 0.16.17
+      '@esbuild/linux-x64': 0.16.17
+      '@esbuild/netbsd-x64': 0.16.17
+      '@esbuild/openbsd-x64': 0.16.17
+      '@esbuild/sunos-x64': 0.16.17
+      '@esbuild/win32-arm64': 0.16.17
+      '@esbuild/win32-ia32': 0.16.17
+      '@esbuild/win32-x64': 0.16.17
 
   /escalade/3.1.1:
     resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
     engines: {node: '>=6'}
     dev: true
 
+  /escape-goat/2.1.1:
+    resolution: {integrity: sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /escape-html/1.0.3:
+    resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+    dev: true
+
   /escape-string-regexp/1.0.5:
     resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
     engines: {node: '>=0.8.0'}
@@ -3820,6 +3996,12 @@ packages:
     resolution: {integrity: sha512-d9cEfo/WcOezgPLAC/8t8wGb6YOD6JTCPMw2QcG2nAdFmyY+9rTUizCTaGjIZAloWENTEUMAPpkUAIJJJ0i96A==}
     dev: true
 
+  /fast-url-parser/1.1.3:
+    resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==}
+    dependencies:
+      punycode: 1.4.1
+    dev: true
+
   /fastq/1.15.0:
     resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
     dependencies:
@@ -3852,6 +4034,21 @@ packages:
       to-regex-range: 5.0.1
     dev: true
 
+  /finalhandler/1.1.2:
+    resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==}
+    engines: {node: '>= 0.8'}
+    dependencies:
+      debug: 2.6.9
+      encodeurl: 1.0.2
+      escape-html: 1.0.3
+      on-finished: 2.3.0
+      parseurl: 1.3.3
+      statuses: 1.5.0
+      unpipe: 1.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /find-up/2.1.0:
     resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==}
     engines: {node: '>=4'}
@@ -4070,6 +4267,18 @@ packages:
       is-glob: 4.0.3
     dev: true
 
+  /glob-slash/1.0.0:
+    resolution: {integrity: sha512-ZwFh34WZhZX28ntCMAP1mwyAJkn8+Omagvt/GvA+JQM/qgT0+MR2NPF3vhvgdshfdvDyGZXs8fPXW84K32Wjuw==}
+    dev: true
+
+  /glob-slasher/1.0.1:
+    resolution: {integrity: sha512-5MUzqFiycIKLMD1B0dYOE4hGgLLUZUNGGYO4BExdwT32wUwW3DBOE7lMQars7vB1q43Fb3Tyt+HmgLKsJhDYdg==}
+    dependencies:
+      glob-slash: 1.0.0
+      lodash.isobject: 2.4.1
+      toxic: 1.0.1
+    dev: true
+
   /glob/7.1.4:
     resolution: {integrity: sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==}
     dependencies:
@@ -4114,6 +4323,13 @@ packages:
       once: 1.4.0
     dev: true
 
+  /global-dirs/3.0.1:
+    resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==}
+    engines: {node: '>=10'}
+    dependencies:
+      ini: 2.0.0
+    dev: true
+
   /globals/11.12.0:
     resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
     engines: {node: '>=4'}
@@ -4181,6 +4397,11 @@ packages:
     resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
     dev: true
 
+  /has-yarn/2.1.0:
+    resolution: {integrity: sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==}
+    engines: {node: '>=8'}
+    dev: true
+
   /has/1.0.3:
     resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
     engines: {node: '>= 0.4.0'}
@@ -4297,6 +4518,11 @@ packages:
       resolve-from: 4.0.0
     dev: true
 
+  /import-lazy/2.1.0:
+    resolution: {integrity: sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==}
+    engines: {node: '>=4'}
+    dev: true
+
   /import-local/3.1.0:
     resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
     engines: {node: '>=8'}
@@ -4335,6 +4561,11 @@ packages:
     resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
     dev: true
 
+  /ini/2.0.0:
+    resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==}
+    engines: {node: '>=10'}
+    dev: true
+
   /init-package-json/3.0.2:
     resolution: {integrity: sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A==}
     engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@@ -4369,6 +4600,12 @@ packages:
       wrap-ansi: 7.0.0
     dev: true
 
+  /install-artifact-from-github/1.3.2:
+    resolution: {integrity: sha512-yCFcLvqk0yQdxx0uJz4t9Z3adDMLAYrcGYv546uRXCSvxE+GqNYhhz/KmrGcUKGI/gVLR9n/e/zM9jX/+ASMJQ==}
+    hasBin: true
+    dev: true
+    optional: true
+
   /ip/2.0.0:
     resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==}
     dev: true
@@ -4444,6 +4681,14 @@ packages:
       is-extglob: 2.1.1
     dev: true
 
+  /is-installed-globally/0.4.0:
+    resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      global-dirs: 3.0.1
+      is-path-inside: 3.0.3
+    dev: true
+
   /is-interactive/1.0.0:
     resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
     engines: {node: '>=8'}
@@ -4457,6 +4702,11 @@ packages:
     resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
     dev: true
 
+  /is-npm/5.0.0:
+    resolution: {integrity: sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==}
+    engines: {node: '>=10'}
+    dev: true
+
   /is-number/7.0.0:
     resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
     engines: {node: '>=0.12.0'}
@@ -4467,6 +4717,11 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
+  /is-path-inside/3.0.3:
+    resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+    engines: {node: '>=8'}
+    dev: true
+
   /is-plain-obj/1.1.0:
     resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
     engines: {node: '>=0.10.0'}
@@ -4537,6 +4792,10 @@ packages:
     engines: {node: '>=10'}
     dev: true
 
+  /is-url/1.2.4:
+    resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==}
+    dev: true
+
   /is-wsl/2.2.0:
     resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
     engines: {node: '>=8'}
@@ -4544,6 +4803,14 @@ packages:
       is-docker: 2.2.1
     dev: true
 
+  /is-yarn-global/0.3.0:
+    resolution: {integrity: sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==}
+    dev: true
+
+  /isarray/0.0.1:
+    resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==}
+    dev: true
+
   /isarray/1.0.0:
     resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
     dev: true
@@ -4557,6 +4824,15 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
+  /isomorphic-fetch/3.0.0:
+    resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==}
+    dependencies:
+      node-fetch: 2.6.8
+      whatwg-fetch: 3.6.2
+    transitivePeerDependencies:
+      - encoding
+    dev: true
+
   /istanbul-lib-coverage/3.2.0:
     resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==}
     engines: {node: '>=8'}
@@ -4929,7 +5205,7 @@ packages:
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
       '@babel/core': 7.20.12
-      '@babel/generator': 7.20.7
+      '@babel/generator': 7.20.14
       '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.12
       '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.12
       '@babel/traverse': 7.20.13
@@ -5024,6 +5300,14 @@ packages:
       - ts-node
     dev: true
 
+  /join-path/1.1.1:
+    resolution: {integrity: sha512-jnt9OC34sLXMLJ6YfPQ2ZEKrR9mB5ZbSnQb4LPaOx1c5rTzxpR33L18jjp0r75mGGTJmsil3qwN1B5IBeTnSSA==}
+    dependencies:
+      as-array: 2.0.0
+      url-join: 0.0.1
+      valid-url: 1.0.9
+    dev: true
+
   /joycon/3.1.1:
     resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
     engines: {node: '>=10'}
@@ -5136,15 +5420,15 @@ packages:
       '@lerna/init': 6.4.1
       '@lerna/link': 6.4.1
       '@lerna/list': 6.4.1
-      '@lerna/publish': 6.4.1_nx@15.6.2+typescript@4.9.4
+      '@lerna/publish': 6.4.1_nx@15.6.3+typescript@4.9.4
       '@lerna/run': 6.4.1
       '@lerna/validation-error': 6.4.1
-      '@lerna/version': 6.4.1_nx@15.6.2+typescript@4.9.4
-      '@nrwl/devkit': 15.6.2_nx@15.6.2+typescript@4.9.4
+      '@lerna/version': 6.4.1_nx@15.6.3+typescript@4.9.4
+      '@nrwl/devkit': 15.6.3_nx@15.6.3+typescript@4.9.4
       import-local: 3.1.0
       inquirer: 8.2.5
       npmlog: 6.0.2
-      nx: 15.6.2
+      nx: 15.6.3
       typescript: 4.9.4
     transitivePeerDependencies:
       - '@swc-node/register'
@@ -5293,10 +5577,20 @@ packages:
       p-locate: 4.1.0
     dev: true
 
+  /lodash._objecttypes/2.4.1:
+    resolution: {integrity: sha512-XpqGh1e7hhkOzftBfWE7zt+Yn9mVHFkDhicVttvKLsoCMLVVL+xTQjfjB4X4vtznauxv0QZ5ZAeqjvat0dh62Q==}
+    dev: true
+
   /lodash.ismatch/4.4.0:
     resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==}
     dev: true
 
+  /lodash.isobject/2.4.1:
+    resolution: {integrity: sha512-sTebg2a1PoicYEZXD5PBdQcTlIJ6hUslrlWr7iV0O7n+i4596s2NQ9I5CaZ5FbXSfya/9WQsrYLANUJv9paYVA==}
+    dependencies:
+      lodash._objecttypes: 2.4.1
+    dev: true
+
   /lodash.kebabcase/4.1.1:
     resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
     dev: true
@@ -5464,6 +5758,11 @@ packages:
     engines: {node: '>= 8'}
     dev: true
 
+  /methods/1.1.2:
+    resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
+    engines: {node: '>= 0.6'}
+    dev: true
+
   /micromatch/4.0.5:
     resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
     engines: {node: '>=8.6'}
@@ -5626,6 +5925,23 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
+  /morgan/1.10.0:
+    resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      basic-auth: 2.0.1
+      debug: 2.6.9
+      depd: 2.0.0
+      on-finished: 2.3.0
+      on-headers: 1.0.2
+    transitivePeerDependencies:
+      - supports-color
+    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==}
     dev: true
@@ -5657,6 +5973,11 @@ packages:
       thenify-all: 1.6.0
     dev: true
 
+  /nan/2.17.0:
+    resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==}
+    dev: true
+    optional: true
+
   /natural-compare/1.4.0:
     resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
     dev: true
@@ -5890,8 +6211,8 @@ packages:
       set-blocking: 2.0.0
     dev: true
 
-  /nx/15.6.2:
-    resolution: {integrity: sha512-F6O2mRf6fWVVpkekvmN2erlJZ8jFVRO+PlAKxHBd8pFGtqkh53VXtU0r7/93qgRjC1zz9VVd8BKEB+xuQ2FbDQ==}
+  /nx/15.6.3:
+    resolution: {integrity: sha512-3t0A0GPLNen1yPAyE+VGZ3nkAzZYb5nfXtAcx8SHBlKq4u42yBY3khBmP1y4Og3jhIwFIj7J7Npeh8ZKrthmYQ==}
     hasBin: true
     requiresBuild: true
     peerDependencies:
@@ -5903,8 +6224,8 @@ packages:
       '@swc/core':
         optional: true
     dependencies:
-      '@nrwl/cli': 15.6.2
-      '@nrwl/tao': 15.6.2
+      '@nrwl/cli': 15.6.3
+      '@nrwl/tao': 15.6.3
       '@parcel/watcher': 2.0.4
       '@yarnpkg/lockfile': 1.1.0
       '@yarnpkg/parsers': 3.0.0-rc.36
@@ -5951,6 +6272,25 @@ packages:
     resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
     dev: true
 
+  /on-finished/2.3.0:
+    resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
+    engines: {node: '>= 0.8'}
+    dependencies:
+      ee-first: 1.1.1
+    dev: true
+
+  /on-finished/2.4.1:
+    resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+    engines: {node: '>= 0.8'}
+    dependencies:
+      ee-first: 1.1.1
+    dev: true
+
+  /on-headers/1.0.2:
+    resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
   /once/1.4.0:
     resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
     dependencies:
@@ -6180,6 +6520,11 @@ packages:
       parse-path: 7.0.0
     dev: true
 
+  /parseurl/1.3.3:
+    resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
   /path-exists/3.0.0:
     resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
     engines: {node: '>=4'}
@@ -6214,6 +6559,16 @@ packages:
     resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
     dev: true
 
+  /path-to-regexp/0.1.7:
+    resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
+    dev: true
+
+  /path-to-regexp/1.8.0:
+    resolution: {integrity: sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==}
+    dependencies:
+      isarray: 0.0.1
+    dev: true
+
   /path-type/3.0.0:
     resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==}
     engines: {node: '>=4'}
@@ -6273,19 +6628,19 @@ packages:
       find-up: 4.1.0
     dev: true
 
-  /playwright-core/1.28.1:
-    resolution: {integrity: sha512-3PixLnGPno0E8rSBJjtwqTwJe3Yw72QwBBBxNoukIj3lEeBNXwbNiKrNuB1oyQgTBw5QHUhNO3SteEtHaMK6ag==}
+  /playwright-core/1.30.0:
+    resolution: {integrity: sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g==}
     engines: {node: '>=14'}
     hasBin: true
     dev: true
 
-  /playwright/1.28.1:
-    resolution: {integrity: sha512-92Sz6XBlfHlb9tK5UCDzIFAuIkHHpemA9zwUaqvo+w7sFMSmVMGmvKcbptof/eJObq63PGnMhM75x7qxhTR78Q==}
+  /playwright/1.30.0:
+    resolution: {integrity: sha512-ENbW5o75HYB3YhnMTKJLTErIBExrSlX2ZZ1C/FzmHjUYIfxj/UnI+DWpQr992m+OQVSg0rCExAOlRwB+x+yyIg==}
     engines: {node: '>=14'}
     hasBin: true
     requiresBuild: true
     dependencies:
-      playwright-core: 1.28.1
+      playwright-core: 1.30.0
     dev: true
 
   /postcss-load-config/3.1.4:
@@ -6383,11 +6738,22 @@ packages:
     resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
     dev: true
 
+  /punycode/1.4.1:
+    resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==}
+    dev: true
+
   /punycode/2.3.0:
     resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
     engines: {node: '>=6'}
     dev: true
 
+  /pupa/2.1.1:
+    resolution: {integrity: sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==}
+    engines: {node: '>=8'}
+    dependencies:
+      escape-goat: 2.1.1
+    dev: true
+
   /q/1.5.1:
     resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==}
     engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
@@ -6408,6 +6774,29 @@ packages:
       safe-buffer: 5.2.1
     dev: true
 
+  /rc/1.2.8:
+    resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+    hasBin: true
+    dependencies:
+      deep-extend: 0.6.0
+      ini: 1.3.8
+      minimist: 1.2.7
+      strip-json-comments: 2.0.1
+    dev: true
+
+  /re2/1.18.0:
+    resolution: {integrity: sha512-MoCYZlJ9YUgksND9asyNF2/x532daXU/ARp1UeJbQ5flMY6ryKNEhrWt85aw3YluzOJlC3vXpGgK2a1jb0b4GA==}
+    requiresBuild: true
+    dependencies:
+      install-artifact-from-github: 1.3.2
+      nan: 2.17.0
+      node-gyp: 9.3.1
+    transitivePeerDependencies:
+      - bluebird
+      - supports-color
+    dev: true
+    optional: true
+
   /react-is/18.2.0:
     resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
     dev: true
@@ -6524,6 +6913,20 @@ packages:
       strip-indent: 3.0.0
     dev: true
 
+  /registry-auth-token/5.0.1:
+    resolution: {integrity: sha512-UfxVOj8seK1yaIOiieV4FIP01vfBDLsY0H9sQzi9EbbUdJiuuBjJgLa1DpImXMNPnVkBD4eVxTEXcrZA6kfpJA==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@pnpm/npm-conf': 1.0.5
+    dev: true
+
+  /registry-url/5.1.0:
+    resolution: {integrity: sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==}
+    engines: {node: '>=8'}
+    dependencies:
+      rc: 1.2.8
+    dev: true
+
   /require-directory/2.1.1:
     resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
     engines: {node: '>=0.10.0'}
@@ -6612,7 +7015,7 @@ packages:
       is-plain-object: 3.0.1
     dev: true
 
-  /rollup-plugin-dts/5.1.1_yjrzni4zyr7xhg3xsvmmijxnvu:
+  /rollup-plugin-dts/5.1.1_tkwgik6422u3whqaozmypsnvni:
     resolution: {integrity: sha512-zpgo52XmnLg8w4k3MScinFHZK1+ro6r7uVe34fJ0Ee8AM45FvgvTuvfWWaRgIpA4pQ1BHJuu2ospncZhkcJVeA==}
     engines: {node: '>=v14'}
     peerDependencies:
@@ -6620,38 +7023,53 @@ packages:
       typescript: ^4.1
     dependencies:
       magic-string: 0.27.0
-      rollup: 3.11.0
+      rollup: 3.12.0
       typescript: 4.9.4
     optionalDependencies:
       '@babel/code-frame': 7.18.6
     dev: true
 
-  /rollup-plugin-esbuild/5.0.0_h6jqhw2rq3gbm5ffzodjfjev5e:
+  /rollup-plugin-esbuild/5.0.0_7k6ev2cyiz7vefgkiohpkhn6r4:
     resolution: {integrity: sha512-1cRIOHAPh8WQgdQQyyvFdeOdxuiyk+zB5zJ5+YOwrZP4cJ0MT3Fs48pQxrZeyZHcn+klFherytILVfE4aYrneg==}
     engines: {node: '>=14.18.0', npm: '>=8.0.0'}
     peerDependencies:
       esbuild: '>=0.10.1'
       rollup: ^1.20.0 || ^2.0.0 || ^3.0.0
     dependencies:
-      '@rollup/pluginutils': 5.0.2_rollup@3.11.0
+      '@rollup/pluginutils': 5.0.2_rollup@3.12.0
       debug: 4.3.4
       es-module-lexer: 1.1.0
-      esbuild: 0.16.7
+      esbuild: 0.16.17
       joycon: 3.1.1
       jsonc-parser: 3.2.0
-      rollup: 3.11.0
+      rollup: 3.12.0
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /rollup/3.11.0:
-    resolution: {integrity: sha512-+uWPPkpWQ2H3Qi7sNBcRfhhHJyUNgBYhG4wKe5wuGRj2m55kpo+0p5jubKNBjQODyPe6tSBE3tNpdDwEisQvAQ==}
+  /rollup/3.12.0:
+    resolution: {integrity: sha512-4MZ8kA2HNYahIjz63rzrMMRvDqQDeS9LoriJvMuV0V6zIGysP36e9t4yObUfwdT9h/szXoHQideICftcdZklWg==}
     engines: {node: '>=14.18.0', npm: '>=8.0.0'}
     hasBin: true
     optionalDependencies:
       fsevents: 2.3.2
     dev: true
 
+  /router/1.3.7:
+    resolution: {integrity: sha512-bYnD9Vv2287+g3AIll2kHITLtHV5+fldq6hVzaul9RbdGme77mvBY/1cO+ahsgstA2RI6DSg/j4W1TYHm4Lz4g==}
+    engines: {node: '>= 0.8'}
+    dependencies:
+      array-flatten: 3.0.0
+      debug: 2.6.9
+      methods: 1.1.2
+      parseurl: 1.3.3
+      path-to-regexp: 0.1.7
+      setprototypeof: 1.2.0
+      utils-merge: 1.0.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /run-async/2.4.1:
     resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
     engines: {node: '>=0.12.0'}
@@ -6688,6 +7106,13 @@ packages:
     resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
     dev: true
 
+  /semver-diff/3.1.1:
+    resolution: {integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==}
+    engines: {node: '>=8'}
+    dependencies:
+      semver: 6.3.0
+    dev: true
+
   /semver/5.7.1:
     resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
     hasBin: true
@@ -6728,6 +7153,10 @@ packages:
     resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
     dev: true
 
+  /setprototypeof/1.2.0:
+    resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+    dev: true
+
   /shallow-clone/3.0.1:
     resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
     engines: {node: '>=8'}
@@ -6918,6 +7347,11 @@ packages:
       escape-string-regexp: 2.0.0
     dev: true
 
+  /statuses/1.5.0:
+    resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==}
+    engines: {node: '>= 0.6'}
+    dev: true
+
   /string-argv/0.3.1:
     resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==}
     engines: {node: '>=0.6.19'}
@@ -7016,6 +7450,11 @@ packages:
       min-indent: 1.0.1
     dev: true
 
+  /strip-json-comments/2.0.1:
+    resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
   /strip-json-comments/3.1.1:
     resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
     engines: {node: '>=8'}
@@ -7044,6 +7483,37 @@ packages:
       ts-interface-checker: 0.1.13
     dev: true
 
+  /superstatic/9.0.2:
+    resolution: {integrity: sha512-eKX9qubOaJbtdxn4gWhVVMXuno8cn0WPKOYgLAmLwYiHafrASXAIXHzL3Jx7w06yXiaM5e1DA2Ezeb08iV28+A==}
+    engines: {node: ^14.18.0 || >=16.4.0}
+    hasBin: true
+    dependencies:
+      basic-auth-connect: 1.0.0
+      commander: 9.5.0
+      compression: 1.7.4
+      connect: 3.7.0
+      destroy: 1.2.0
+      fast-url-parser: 1.1.3
+      glob-slasher: 1.0.1
+      is-url: 1.2.4
+      join-path: 1.1.1
+      lodash: 4.17.21
+      mime-types: 2.1.35
+      minimatch: 5.1.6
+      morgan: 1.10.0
+      on-finished: 2.4.1
+      on-headers: 1.0.2
+      path-to-regexp: 1.8.0
+      router: 1.3.7
+      update-notifier-cjs: 5.1.6
+    optionalDependencies:
+      re2: 1.18.0
+    transitivePeerDependencies:
+      - bluebird
+      - encoding
+      - supports-color
+    dev: true
+
   /supports-color/5.5.0:
     resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
     engines: {node: '>=4'}
@@ -7187,6 +7657,12 @@ packages:
       is-number: 7.0.0
     dev: true
 
+  /toxic/1.0.1:
+    resolution: {integrity: sha512-WI3rIGdcaKULYg7KVoB0zcjikqvcYYvcuT6D89bFPz2rVR0Rl0PK6x8/X62rtdLtBKIE985NzVf/auTtGegIIg==}
+    dependencies:
+      lodash: 4.17.21
+    dev: true
+
   /tr46/0.0.3:
     resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
     dev: true
@@ -7220,7 +7696,7 @@ packages:
     resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
     dev: true
 
-  /ts-jest/29.0.5_eks76w3tabv3bn6sckcjgzhh44:
+  /ts-jest/29.0.5_fcfrzhucaalut4icxzmgymelre:
     resolution: {integrity: sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     hasBin: true
@@ -7242,7 +7718,7 @@ packages:
         optional: true
     dependencies:
       bs-logger: 0.2.6
-      esbuild: 0.16.7
+      esbuild: 0.16.17
       fast-json-stable-stringify: 2.1.0
       jest: 29.4.1_@types+node@18.11.18
       jest-util: 29.4.1
@@ -7293,7 +7769,7 @@ packages:
       joycon: 3.1.1
       postcss-load-config: 3.1.4
       resolve-from: 5.0.0
-      rollup: 3.11.0
+      rollup: 3.12.0
       source-map: 0.8.0-beta.0
       sucrase: 3.29.0
       tree-kill: 1.2.2
@@ -7324,6 +7800,11 @@ packages:
     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.21.3:
     resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
     engines: {node: '>=10'}
@@ -7391,6 +7872,13 @@ packages:
       imurmurhash: 0.1.4
     dev: true
 
+  /unique-string/2.0.0:
+    resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
+    engines: {node: '>=8'}
+    dependencies:
+      crypto-random-string: 2.0.0
+    dev: true
+
   /universal-user-agent/6.0.0:
     resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==}
     dev: true
@@ -7405,6 +7893,11 @@ packages:
     engines: {node: '>= 10.0.0'}
     dev: true
 
+  /unpipe/1.0.0:
+    resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
   /unzipper/0.10.11:
     resolution: {integrity: sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==}
     dependencies:
@@ -7436,10 +7929,43 @@ packages:
       picocolors: 1.0.0
     dev: true
 
+  /update-notifier-cjs/5.1.6:
+    resolution: {integrity: sha512-wgxdSBWv3x/YpMzsWz5G4p4ec7JWD0HCl8W6bmNB6E5Gwo+1ym5oN4hiXpLf0mPySVEJEIsYlkshnplkg2OP9A==}
+    engines: {node: '>=14'}
+    dependencies:
+      boxen: 5.1.2
+      chalk: 4.1.2
+      configstore: 5.0.1
+      has-yarn: 2.1.0
+      import-lazy: 2.1.0
+      is-ci: 2.0.0
+      is-installed-globally: 0.4.0
+      is-npm: 5.0.0
+      is-yarn-global: 0.3.0
+      isomorphic-fetch: 3.0.0
+      pupa: 2.1.1
+      registry-auth-token: 5.0.1
+      registry-url: 5.1.0
+      semver: 7.3.8
+      semver-diff: 3.1.1
+      xdg-basedir: 4.0.0
+    transitivePeerDependencies:
+      - encoding
+    dev: true
+
+  /url-join/0.0.1:
+    resolution: {integrity: sha512-H6dnQ/yPAAVzMQRvEvyz01hhfQL5qRWSEt7BX8t9DqnPw9BjMb64fjIRq76Uvf1hkHp+mTZvEVJ5guXOT0Xqaw==}
+    dev: true
+
   /util-deprecate/1.0.2:
     resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
     dev: true
 
+  /utils-merge/1.0.1:
+    resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
+    engines: {node: '>= 0.4.0'}
+    dev: true
+
   /uuid/8.3.2:
     resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
     hasBin: true
@@ -7458,6 +7984,10 @@ packages:
       convert-source-map: 1.9.0
     dev: true
 
+  /valid-url/1.0.9:
+    resolution: {integrity: sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==}
+    dev: true
+
   /validate-npm-package-license/3.0.4:
     resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
     dependencies:
@@ -7478,6 +8008,11 @@ packages:
       builtins: 5.0.1
     dev: true
 
+  /vary/1.1.2:
+    resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
   /vscode-oniguruma/1.7.0:
     resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==}
     dev: false
@@ -7510,6 +8045,10 @@ packages:
     resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
     dev: true
 
+  /whatwg-fetch/3.6.2:
+    resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==}
+    dev: true
+
   /whatwg-url/5.0.0:
     resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
     dependencies:
@@ -7546,6 +8085,13 @@ packages:
       string-width: 4.2.3
     dev: true
 
+  /widest-line/3.1.0:
+    resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==}
+    engines: {node: '>=8'}
+    dependencies:
+      string-width: 4.2.3
+    dev: true
+
   /wordwrap/1.0.0:
     resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
     dev: true
@@ -7638,6 +8184,11 @@ packages:
       write-json-file: 3.2.0
     dev: true
 
+  /xdg-basedir/4.0.0:
+    resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==}
+    engines: {node: '>=8'}
+    dev: true
+
   /xtend/4.0.2:
     resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
     engines: {node: '>=0.4'}
diff --git a/scripts/e2e/local-server.mjs b/scripts/e2e/local-server.mjs
new file mode 100755
index 000000000..2cadfa891
--- /dev/null
+++ b/scripts/e2e/local-server.mjs
@@ -0,0 +1,37 @@
+import { server } from 'superstatic'
+import {
+  DIR_CUSTOM_LANGUAGES,
+  DIR_CUSTOM_THEMES,
+  DIR_CUSTOM_WASM,
+  DIR_DEFAULT_LANGUAGES,
+  DIR_DEFAULT_THEMES,
+  DIR_DEFAULT_WASM,
+  DIR_ROOT_CDN,
+  TARGET_WEBSERVER
+} from './shared.mjs'
+
+const PORT = process.env.PORT || 3000
+
+const app = server({
+  cwd: TARGET_WEBSERVER,
+  port: PORT,
+  compression: true,
+  config: {
+    redirects: [
+      createRedirectObject(DIR_CUSTOM_LANGUAGES, DIR_DEFAULT_LANGUAGES),
+      createRedirectObject(DIR_CUSTOM_THEMES, DIR_DEFAULT_THEMES),
+      createRedirectObject(DIR_CUSTOM_WASM, DIR_DEFAULT_WASM),
+      createRedirectObject(DIR_ROOT_CDN + DIR_DEFAULT_LANGUAGES, DIR_DEFAULT_LANGUAGES),
+      createRedirectObject(DIR_ROOT_CDN + DIR_DEFAULT_THEMES, DIR_DEFAULT_THEMES),
+      createRedirectObject(DIR_ROOT_CDN + DIR_DEFAULT_WASM, DIR_DEFAULT_WASM)
+    ]
+  }
+})
+
+app.listen(() => {
+  console.log(`Local E2E server started on port ${PORT}.`)
+})
+
+function createRedirectObject(source, target) {
+  return { source: `${source}/:file`, destination: `${target}/:file`, type: 307 }
+}
diff --git a/scripts/e2e/setup.mjs b/scripts/e2e/setup.mjs
new file mode 100644
index 000000000..ad94e024b
--- /dev/null
+++ b/scripts/e2e/setup.mjs
@@ -0,0 +1,35 @@
+import fsExtra from 'fs-extra'
+import {
+  SOURCE_HTML_FIXTURES,
+  SOURCE_ASSETS_JS_WASM,
+  SOURCE_ASSETS_LANGUAGES,
+  SOURCE_ASSETS_THEMES,
+  TARGET_WEBSERVER,
+  TARGET_ASSETS_JS_WASM,
+  TARGET_ASSETS_LANGUAGES,
+  TARGET_ASSETS_THEMES
+} from './shared.mjs'
+
+function globalSetup() {
+  if (!fsExtra.existsSync(TARGET_WEBSERVER)) {
+    fsExtra.mkdirSync(TARGET_WEBSERVER, { recursive: true })
+  }
+  if (!fsExtra.existsSync(TARGET_ASSETS_JS_WASM)) {
+    fsExtra.mkdirSync(TARGET_ASSETS_JS_WASM)
+  }
+  if (!fsExtra.existsSync(TARGET_ASSETS_LANGUAGES)) {
+    fsExtra.mkdirSync(TARGET_ASSETS_LANGUAGES)
+  }
+  if (!fsExtra.existsSync(SOURCE_ASSETS_THEMES)) {
+    fsExtra.mkdirSync(SOURCE_ASSETS_THEMES)
+  }
+
+  fsExtra.copySync(SOURCE_HTML_FIXTURES, TARGET_WEBSERVER)
+  fsExtra.copySync(SOURCE_ASSETS_JS_WASM, TARGET_ASSETS_JS_WASM)
+  fsExtra.copySync(SOURCE_ASSETS_LANGUAGES, TARGET_ASSETS_LANGUAGES)
+  fsExtra.copySync(SOURCE_ASSETS_THEMES, TARGET_ASSETS_THEMES)
+}
+
+export default globalSetup
+
+// globalSetup()
diff --git a/scripts/e2e/shared.mjs b/scripts/e2e/shared.mjs
new file mode 100644
index 000000000..848dc5374
--- /dev/null
+++ b/scripts/e2e/shared.mjs
@@ -0,0 +1,31 @@
+import { join } from 'path'
+
+const SHIKI_BASE_DIR = join(process.cwd(), 'packages', 'shiki')
+
+// Default server paths for assets
+export const DIR_DEFAULT_LANGUAGES = '/languages'
+export const DIR_DEFAULT_THEMES = '/themes'
+export const DIR_DEFAULT_WASM = '/dist'
+
+// Custom server paths for assets
+export const DIR_CUSTOM_LANGUAGES = '/custom/langs'
+export const DIR_CUSTOM_THEMES = '/custom/theme'
+export const DIR_CUSTOM_WASM = '/custom/bin'
+
+// Custom root path as "CDN"
+export const DIR_ROOT_CDN = '/assets'
+
+// Source folders with html files
+export const SOURCE_HTML_FIXTURES = join(SHIKI_BASE_DIR, 'src', '__tests__', '__fixtures__')
+// Source folder with JS and WASM files
+export const SOURCE_ASSETS_JS_WASM = join(SHIKI_BASE_DIR, DIR_DEFAULT_WASM)
+// Source folder with languages
+export const SOURCE_ASSETS_LANGUAGES = join(SHIKI_BASE_DIR, DIR_DEFAULT_LANGUAGES)
+// Source folder with themes
+export const SOURCE_ASSETS_THEMES = join(SHIKI_BASE_DIR, DIR_DEFAULT_THEMES)
+
+// Target folders for serving content
+export const TARGET_WEBSERVER = join(process.cwd(), 'tmp', 'superstatic-e2e')
+export const TARGET_ASSETS_JS_WASM = join(TARGET_WEBSERVER, DIR_DEFAULT_WASM)
+export const TARGET_ASSETS_LANGUAGES = join(TARGET_WEBSERVER, DIR_DEFAULT_LANGUAGES)
+export const TARGET_ASSETS_THEMES = join(TARGET_WEBSERVER, DIR_DEFAULT_THEMES)
diff --git a/scripts/e2e/teardown.mjs b/scripts/e2e/teardown.mjs
new file mode 100644
index 000000000..76f2ff98c
--- /dev/null
+++ b/scripts/e2e/teardown.mjs
@@ -0,0 +1,8 @@
+import fsExtra from 'fs-extra'
+import { TARGET_WEBSERVER } from './shared.mjs'
+
+export default () => {
+  if (fsExtra.existsSync(TARGET_WEBSERVER)) {
+    fsExtra.rm(TARGET_WEBSERVER, { force: true, recursive: true })
+  }
+}