diff --git a/.eslintignore b/.eslintignore
index 92a9a83e..2ef2464d 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -11,3 +11,4 @@ releases
.tmp
.env
scripts
+vitest.config.ts
diff --git a/.gitignore b/.gitignore
index 3d725187..18964234 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,8 +3,7 @@ node_modules
.idea
typedocs
dist
-dist-cfg
-dist-vitest
+dist-*
examples/dist-tsc
visual-regression/failed-results
visual-regression/certified-snapshots/*-local
diff --git a/Dockerfile b/Dockerfile
index 253dae7b..e0937ed3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,13 +4,13 @@ FROM mcr.microsoft.com/playwright:v1.39.0-jammy
# Set the working directory
WORKDIR /work
-# Install PNPM
-RUN npm install -g pnpm
-
# Copy the necessary files to the container
COPY .npmrc .npmrc
COPY package.json package.json
+# Install PNPM
+RUN corepack prepare && corepack enable
+
# Get pnpm to install the version of Node declared in .npmrc
RUN pnpm exec ls
diff --git a/README.md b/README.md
index ced14933..141c7300 100644
--- a/README.md
+++ b/README.md
@@ -89,145 +89,42 @@ See [docs/ManualRegressionTests.md].
See [RELEASE.md](./RELEASE.md)
-## Main Space vs Core Space
+## Installing Fonts
-The Lightning 3 Renderer runs code in two logically seperate environments:
-the **Main Space** and the **Core Space**.
-
-Users of the Renderer will write most of their code for the Main Space using
-the **Main API**. This is code that will always run on the browser's main thread
-and includes initializing the Renderer, creating/modifying/destroying nodes,
-controlling animations, etc.
-
-The Core Space is where the actual rendering of each UI frame happens and is
-mostly meant to be transparent to users of the Renderer. However, the Core Space
-is where all of the code that must be tightly coupled to the rendering process
-must be loaded and run. The Core Space is extendible by users by writing
-**Core Extensions** via the **Core API**. This allows for users to develop their
-own shaders, textures, text renderers, dynamic shader effects, and more. Fonts
-used in an application must be loaded in this way too. The Core Space exists
-seperately from the Main Space because it is allowed to execute on the page's
-main thread OR a Web Worker thread. A **Core Driver** (see below) is used to
-bridge the Main Space with the Core Space.
-
-## Core Drivers
-
-The Lightning 3 Renderer is designed to be able to use a single thread or
-multiple web worker threads based on the configuration of a **Core Driver**.
-
-A Core Driver essentially acts as a bridge between the Main and Core spaces
-defined above.
-
-The Renderer comes with two Core Drivers: the Main Core Driver for single
-threaded rendering and the ThreadX Core Driver for multi-threaded rendering.
-
-NOTE: The ThreadX Core Driver is experimental and even when the Renderer
-graduates from beta may still not be ready for production use.
-
-### Main Core Driver
-
-The Main Core Driver renders your application on the web page's main thread.
-
-It can be configured into the Renderer like so:
-
-```ts
-import { MainCoreDriver, RendererMain } from '@lightningjs/renderer';
-
-const renderer = new RendererMain(
- {
- // App Config
- },
- 'app', // App div ID
- new MainCoreDriver(), // Main Render driver
-);
-
-// ...
-```
-
-### ThreadX Core Driver
-
-The ThreadX Core Driver renders your application on a seperately spawned
-Web Worker thread.
-
-It can be configured into the Renderer like so:
+Fonts can be installed into the Font Manager exposed by the Renderer's Stage.
+There are two types of fonts that you can install, Web/Canvas2D fonts (WebTrFontFace)
+and SDF fonts (SdfTrFontFace). Install that fonts that your applications needs
+at start up so they are ready when your application is rendered.
```ts
import {
- ThreadXCoreDriver,
RendererMain,
+ WebTrFontFace,
+ SdfTrFontFace,
} from '@lightningjs/renderer';
-// The `@lightningjs/vite-plugin-import-chunk-url` Vite plugin is required for this:
-import coreWorkerUrl from './common/CoreWorker.js?importChunkUrl';
-
const renderer = new RendererMain(
{
- // App Config
+ appWidth: 1920,
+ appHeight: 1080,
+ // ...Other Renderer Config
},
- 'app', // App div ID
- new ThreadXCoreDriver({
- coreWorkerUrl,
- });
+ 'app', // id of div to insert Canvas.
);
-```
-
-## Core Extensions
-
-To load fonts, and/or other custom code into the Core Space, you must write a
-Core Extension and pass it via dynamically importable URL to the initialization
-of the Renderer.
-Just like with loading the ThreadX Core Web Worker for the ThreadX, you import
-your core extension using the `@lightningjs/vite-plugin-import-chunk-url` plugin so that
-it's code is bundled and loaded seperately from your main app's bundle.
-
-You can write a Core Extension by extending the CoreExtension class from the
-Core API like so:
-
-```ts
-import {
- CoreExtension,
- WebTrFontFace,
- SdfTrFontFace,
- type Stage,
-} from '@lightning/renderer/core';
-
-export default class MyCoreExtension extends CoreExtension {
- async run(stage: Stage) {
- // Load fonts into core
- stage.fontManager.addFontFace(
- new WebTrFontFace('Ubuntu', {}, '/fonts/Ubuntu-Regular.ttf'),
- );
-
- stage.fontManager.addFontFace(
- new SdfTrFontFace(
- 'Ubuntu',
- {},
- 'msdf',
- stage,
- '/fonts/Ubuntu-Regular.msdf.png',
- '/fonts/Ubuntu-Regular.msdf.json',
- ),
- );
- }
-}
-```
-
-And then in your application's main entry point you can import it using
-`@lightningjs/vite-plugin-import-chunk-url`:
-
-```ts
-import coreExtensionModuleUrl from './MyCoreExtension.js?importChunkUrl';
-
-// Set up driver, etc.
+// Load fonts into renderer
+renderer.stage.fontManager.addFontFace(
+ new WebTrFontFace('Ubuntu', {}, '/fonts/Ubuntu-Regular.ttf'),
+);
-// Initialize the Renderer
-const renderer = new RendererMain(
- {
- // Other Renderer Config...
- coreExtensionModule: coreExtensionModuleUrl,
- },
- 'app',
- driver,
+renderer.stage.fontManager.addFontFace(
+ new SdfTrFontFace(
+ 'Ubuntu',
+ {},
+ 'msdf',
+ stage,
+ '/fonts/Ubuntu-Regular.msdf.png',
+ '/fonts/Ubuntu-Regular.msdf.json',
+ ),
);
```
diff --git a/docs/CustomShaderEffectTexture.md b/docs/CustomShaderEffectTexture.md
new file mode 100644
index 00000000..ce295db2
--- /dev/null
+++ b/docs/CustomShaderEffectTexture.md
@@ -0,0 +1,5 @@
+# Custom Shaders / Effects / Textures
+
+For some examples on how to create custom shaders, effects and textures, see
+the (custom-shader-effect-texture)[./example-projects/custom-shader-effect-texture]
+example project.
diff --git a/docs/ManualRegressionTests.md b/docs/ManualRegressionTests.md
index efc58172..e688a5aa 100644
--- a/docs/ManualRegressionTests.md
+++ b/docs/ManualRegressionTests.md
@@ -4,49 +4,49 @@ In addition to the automated [Visual Regression Tests](../visual-regression/READ
there are some tests that should be run manually on embedded devices to ensure
the Renderer is working properly.
-## Reference-Based Texture Memory Management Test
+## Critical Texture Memory Cleanup Test
-`?test=reference-texture-memory`
+`?test=texture-cleanup-critical&monitor=true`
-This test confirms the Renderer's ability to proactively garbage collect
-textures that are, at the very least, likely to not be referenced anymore in
-memory.
+This test confirms the Renderer's ability to clean up textures when it never
+has a chance to perform Idle Texture Cleanups.
Within an infinite loop, the test updates the texture of a single full screen
background node to a new random NoiseTexture in rapid succession.
-**Expected Results**: The test runs for at least 1 hour without crashing.
+**Expected Results**: The tests runs for at least 30 mins minutes without
+crashing or the visible Nodes becoming black. The Memory Monitor shows loaded
+textures reaching the Critical Threshold and then falling back to the target.
-To confirm that the textures are being properly disposed of, you can use the Chrome Task Manager to monitor the GPU's memory usage:
+To further confirm that the textures are being properly disposed of, you can use
+the Chrome Task Manager to monitor the GPU's memory usage:
1. Click Window > Task Manager
2. Locate the "GPU Process"
3. Observe the "Memory Footprint" column
-4. The value should eventually drop significantly toward a minimum and/or reach a
- threadhold.
+4. Like the Memory Monitor, the value should increase, and fall significantly
+ repeatedly.
-By default, the ManualCountTextureUsageTracker is used to track texture usage. Also test the experimental FinalizationRegistryTextureUsageTracker instead, by setting the URL param "finalizationRegistry=true".
+## Idle Texture Memory Cleanup Test
-## Threshold-Based Texture Memory Management Test
+`?test=texture-cleanup-idle&monitor=true`
-`?test=threshold-texture-memory`
-
-This test confirms the Renderer's ability to garbage collect textures from GPU VRAM
-that are still referenced and assigned to Nodes but no longer visible within
-the configured `boundsMargin` when the configured `txMemByteThreshold` is
-exceeded.
+This test confirms the Renderer's ability to clean up textures that are no longer
+renderable (not in the configured `boundsMargin`) from GPU VRAM when the Renderer
+becomes idle.
Within an infinite loop, this test generates a grid of Nodes with random NoiseTextures
assigned first completely visible on screen (for at least a frame) and then moves
them outside of the configured `boundsMargin` before repeating the loop.
-**Expected Results**: The tests runs for at least XXXX minutes on an XXXX running WPE
-without crashing or the visible Nodes becoming blank.
+**Expected Results**: The tests runs for at least 30 mins minutes without
+crashing or the visible Nodes becoming black. The Memory Monitor shows loaded
+textures falling to the Target Threshold roughly every 5 seconds.
-To test that the textures are being properly disposed of, you can use the Chrome Task Manager to monitor the GPU's memory usage:
+To further test that the textures are being properly disposed of, you can use the Chrome Task Manager to monitor the GPU's memory usage:
1. Click Window > Task Manager
2. Locate the "GPU Process"
3. Observe the "Memory Footprint" column
-4. The value should eventually drop significantly toward a minimum and/or reach a
- threshold.
+4. Like the Memory Monitor, the value should increase, and fall significantly
+ repeatedly.
diff --git a/docs/example-projects/custom-shader-effect-texture/index.html b/docs/example-projects/custom-shader-effect-texture/index.html
new file mode 100644
index 00000000..9678f140
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/index.html
@@ -0,0 +1,21 @@
+
+
+ Renderer Browser Test
+
+
+
+
+
+
+
diff --git a/docs/example-projects/custom-shader-effect-texture/package.json b/docs/example-projects/custom-shader-effect-texture/package.json
new file mode 100644
index 00000000..0e8dc56a
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "renderer-custom-shader",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "type": "module",
+ "scripts": {
+ "start": "vite --open --host",
+ "build": "tsc && vite build",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "@lightningjs/renderer": "link:../../.."
+ },
+ "devDependencies": {
+ "@types/node": "^20.12.12",
+ "typescript": "^5.4.5",
+ "vite": "^5.2.11"
+ }
+}
diff --git a/docs/example-projects/custom-shader-effect-texture/pnpm-lock.yaml b/docs/example-projects/custom-shader-effect-texture/pnpm-lock.yaml
new file mode 100644
index 00000000..012878dc
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/pnpm-lock.yaml
@@ -0,0 +1,505 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@lightningjs/renderer':
+ specifier: link:../../..
+ version: link:../../..
+ devDependencies:
+ '@types/node':
+ specifier: ^20.12.12
+ version: 20.14.10
+ typescript:
+ specifier: ^5.4.5
+ version: 5.5.3
+ vite:
+ specifier: ^5.2.11
+ version: 5.3.3(@types/node@20.14.10)
+
+packages:
+
+ /@esbuild/aix-ppc64@0.21.5:
+ resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64@0.21.5:
+ resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.21.5:
+ resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.21.5:
+ resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.21.5:
+ resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.21.5:
+ resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.21.5:
+ resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.21.5:
+ resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.21.5:
+ resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.21.5:
+ resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.21.5:
+ resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.21.5:
+ resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.21.5:
+ resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.21.5:
+ resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.21.5:
+ resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.21.5:
+ resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.21.5:
+ resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.21.5:
+ resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.21.5:
+ resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.21.5:
+ resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.21.5:
+ resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.21.5:
+ resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.21.5:
+ resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-android-arm-eabi@4.18.1:
+ resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-android-arm64@4.18.1:
+ resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-arm64@4.18.1:
+ resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-x64@4.18.1:
+ resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-gnueabihf@4.18.1:
+ resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-musleabihf@4.18.1:
+ resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-gnu@4.18.1:
+ resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-musl@4.18.1:
+ resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-powerpc64le-gnu@4.18.1:
+ resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-riscv64-gnu@4.18.1:
+ resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-s390x-gnu@4.18.1:
+ resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-gnu@4.18.1:
+ resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-musl@4.18.1:
+ resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-arm64-msvc@4.18.1:
+ resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-ia32-msvc@4.18.1:
+ resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-x64-msvc@4.18.1:
+ resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@types/estree@1.0.5:
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+ dev: true
+
+ /@types/node@20.14.10:
+ resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==}
+ dependencies:
+ undici-types: 5.26.5
+ dev: true
+
+ /esbuild@0.21.5:
+ resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.21.5
+ '@esbuild/android-arm': 0.21.5
+ '@esbuild/android-arm64': 0.21.5
+ '@esbuild/android-x64': 0.21.5
+ '@esbuild/darwin-arm64': 0.21.5
+ '@esbuild/darwin-x64': 0.21.5
+ '@esbuild/freebsd-arm64': 0.21.5
+ '@esbuild/freebsd-x64': 0.21.5
+ '@esbuild/linux-arm': 0.21.5
+ '@esbuild/linux-arm64': 0.21.5
+ '@esbuild/linux-ia32': 0.21.5
+ '@esbuild/linux-loong64': 0.21.5
+ '@esbuild/linux-mips64el': 0.21.5
+ '@esbuild/linux-ppc64': 0.21.5
+ '@esbuild/linux-riscv64': 0.21.5
+ '@esbuild/linux-s390x': 0.21.5
+ '@esbuild/linux-x64': 0.21.5
+ '@esbuild/netbsd-x64': 0.21.5
+ '@esbuild/openbsd-x64': 0.21.5
+ '@esbuild/sunos-x64': 0.21.5
+ '@esbuild/win32-arm64': 0.21.5
+ '@esbuild/win32-ia32': 0.21.5
+ '@esbuild/win32-x64': 0.21.5
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /picocolors@1.0.1:
+ resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
+ dev: true
+
+ /postcss@8.4.39:
+ resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.1
+ source-map-js: 1.2.0
+ dev: true
+
+ /rollup@4.18.1:
+ resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+ dependencies:
+ '@types/estree': 1.0.5
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.18.1
+ '@rollup/rollup-android-arm64': 4.18.1
+ '@rollup/rollup-darwin-arm64': 4.18.1
+ '@rollup/rollup-darwin-x64': 4.18.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.18.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.18.1
+ '@rollup/rollup-linux-arm64-gnu': 4.18.1
+ '@rollup/rollup-linux-arm64-musl': 4.18.1
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.18.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.18.1
+ '@rollup/rollup-linux-s390x-gnu': 4.18.1
+ '@rollup/rollup-linux-x64-gnu': 4.18.1
+ '@rollup/rollup-linux-x64-musl': 4.18.1
+ '@rollup/rollup-win32-arm64-msvc': 4.18.1
+ '@rollup/rollup-win32-ia32-msvc': 4.18.1
+ '@rollup/rollup-win32-x64-msvc': 4.18.1
+ fsevents: 2.3.3
+ dev: true
+
+ /source-map-js@1.2.0:
+ resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /typescript@5.5.3:
+ resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+ dev: true
+
+ /undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ dev: true
+
+ /vite@5.3.3(@types/node@20.14.10):
+ resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ '@types/node': 20.14.10
+ esbuild: 0.21.5
+ postcss: 8.4.39
+ rollup: 4.18.1
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
diff --git a/docs/example-projects/custom-shader-effect-texture/pnpm-workspace.yaml b/docs/example-projects/custom-shader-effect-texture/pnpm-workspace.yaml
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/example-projects/custom-shader-effect-texture/src/MyCustomEffect.ts b/docs/example-projects/custom-shader-effect-texture/src/MyCustomEffect.ts
new file mode 100644
index 00000000..5e2099f3
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/src/MyCustomEffect.ts
@@ -0,0 +1,77 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+ type DefaultEffectProps,
+ ShaderEffect,
+ type ShaderEffectUniforms,
+} from '@lightningjs/renderer';
+
+/**
+ * Augment the EffectMap interface to include the CustomEffect
+ */
+declare module '@lightningjs/renderer' {
+ interface EffectMap {
+ MyCustomEffect: typeof MyCustomEffect;
+ }
+}
+
+/**
+ * Properties of the {@link MyCustomEffect} effect
+ */
+export interface MyCustomEffectProps extends DefaultEffectProps {
+ /**
+ * Grey scale amount between 0 - 1.
+ *
+ * @default 1
+ */
+ amount?: number;
+}
+
+/**
+ * Grayscale effect grayscales the color values of the current mask color
+ */
+export class MyCustomEffect extends ShaderEffect {
+ static z$__type__Props: MyCustomEffectProps;
+ override readonly name = 'MyCustomEffect';
+
+ static override getEffectKey(): string {
+ return `MyCustomEffect`;
+ }
+
+ static override resolveDefaults(
+ props: MyCustomEffectProps,
+ ): Required {
+ return {
+ amount: props.amount ?? 1,
+ };
+ }
+
+ static override uniforms: ShaderEffectUniforms = {
+ amount: {
+ value: 1,
+ method: 'uniform1f',
+ type: 'float',
+ },
+ };
+
+ static override onColorize = `
+ float grayness = 0.2 * maskColor.r + 0.6 * maskColor.g + 0.2 * maskColor.b;
+ return vec4(amount * vec3(grayness) + (1.0 - amount) * maskColor.rgb, maskColor.a);
+ `;
+}
diff --git a/docs/example-projects/custom-shader-effect-texture/src/MyCustomShader.ts b/docs/example-projects/custom-shader-effect-texture/src/MyCustomShader.ts
new file mode 100644
index 00000000..eea844bd
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/src/MyCustomShader.ts
@@ -0,0 +1,245 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * Based on https://www.shadertoy.com/view/lsVSWW
+ *
+ * @module
+ */
+import {
+ WebGlCoreShader,
+ type DimensionsShaderProp,
+ type WebGlCoreRenderer,
+ type WebGlCoreCtxTexture,
+ type ShaderProgramSources,
+} from '@lightningjs/renderer';
+
+export interface Point {
+ x: number;
+ y: number;
+}
+
+declare module '@lightningjs/renderer' {
+ interface ShaderMap {
+ MyCustomShader: typeof MyCustomShader;
+ }
+}
+
+/**
+ * Properties of the {@link CustomShaderProps} shader
+ */
+export interface CustomShaderProps extends DimensionsShaderProp {
+ /**
+ * Use normalized values rather than pixle values
+ * @default false
+ */
+ normalized?: boolean;
+
+ /**
+ * x & y coordinates of the top left point
+ * @default null
+ */
+ topLeft?: Point | null;
+
+ /**
+ * x & y coordinates of the top right point
+ * @default null
+ */
+ topRight?: Point | null;
+
+ /**
+ * x & y coordinates of the bottom right point
+ * @default null
+ */
+ bottomRight?: Point | null;
+
+ /**
+ * x & y coordinates of the bottom left point
+ * @default null
+ */
+ bottomLeft?: Point | null;
+}
+
+export class MyCustomShader extends WebGlCoreShader {
+ constructor(renderer: WebGlCoreRenderer) {
+ super({
+ renderer,
+ attributes: ['a_position', 'a_textureCoordinate', 'a_color'],
+ uniforms: [
+ { name: 'u_resolution', uniform: 'uniform2fv' },
+ { name: 'u_pixelRatio', uniform: 'uniform1f' },
+ { name: 'u_texture', uniform: 'uniform2f' },
+ { name: 'u_dimensions', uniform: 'uniform2fv' },
+ { name: 'u_topLeft', uniform: 'uniform2fv' },
+ { name: 'u_topRight', uniform: 'uniform2fv' },
+ { name: 'u_bottomRight', uniform: 'uniform2fv' },
+ { name: 'u_bottomLeft', uniform: 'uniform2fv' },
+ ],
+ });
+ }
+
+ static z$__type__Props: CustomShaderProps;
+
+ static override resolveDefaults(
+ props: CustomShaderProps,
+ ): Required {
+ return {
+ normalized: props.normalized || false,
+ topLeft: props.topLeft || null,
+ topRight: props.topRight || null,
+ bottomRight: props.bottomRight || null,
+ bottomLeft: props.bottomLeft || null,
+ $dimensions: {
+ width: 0,
+ height: 0,
+ },
+ };
+ }
+
+ override bindTextures(textures: WebGlCoreCtxTexture[]) {
+ const { glw } = this;
+ glw.activeTexture(0);
+ glw.bindTexture(textures[0]!.ctxTexture);
+ }
+
+ protected override bindProps(props: Required): void {
+ const width = props.normalized ? 1 : props.$dimensions.width;
+ const height = props.normalized ? 1 : props.$dimensions.height;
+
+ const topLeft = [
+ (props.topLeft?.x || 0) / width,
+ (props.topLeft?.y || 0) / height,
+ ];
+
+ const topRight = [
+ (props.topRight?.x || width) / width,
+ (props.topRight?.y || 0) / height,
+ ];
+
+ const bottomRight = [
+ (props.bottomRight?.x || width) / width,
+ (props.bottomRight?.y || height) / height,
+ ];
+
+ const bottomLeft = [
+ (props.bottomLeft?.x || 0) / width,
+ (props.bottomLeft?.y || height) / height,
+ ];
+
+ this.setUniform('u_topLeft', new Float32Array(topLeft));
+ this.setUniform('u_topRight', new Float32Array(topRight));
+ this.setUniform('u_bottomRight', new Float32Array(bottomRight));
+ this.setUniform('u_bottomLeft', new Float32Array(bottomLeft));
+ }
+
+ override canBatchShaderProps(
+ propsA: Required,
+ propsB: Required,
+ ): boolean {
+ return JSON.stringify(propsA) === JSON.stringify(propsB);
+ }
+
+ static override shaderSources: ShaderProgramSources = {
+ vertex: `
+ # ifdef GL_FRAGMENT_PRESICISON_HIGH
+ precision highp float;
+ # else
+ precision mediump float;
+ # endif
+
+ attribute vec2 a_position;
+ attribute vec2 a_textureCoordinate;
+ attribute vec4 a_color;
+
+ uniform vec2 u_resolution;
+ uniform float u_pixelRatio;
+
+ varying vec4 v_color;
+ varying vec2 v_textureCoordinate;
+
+ void main() {
+ vec2 normalized = a_position * u_pixelRatio / u_resolution;
+ vec2 zero_two = normalized * 2.0;
+ vec2 clip_space = zero_two - 1.0;
+
+ // pass to fragment
+ v_color = a_color;
+ v_textureCoordinate = a_textureCoordinate;
+
+ // flip y
+ gl_Position = vec4(clip_space * vec2(1.0, -1.0), 0, 1);
+ }
+ `,
+ fragment: `
+ # ifdef GL_FRAGMENT_PRESICISON_HIGH
+ precision highp float;
+ # else
+ precision mediump float;
+ # endif
+
+ uniform sampler2D u_texture;
+ uniform vec2 u_topLeft;
+ uniform vec2 u_topRight;
+ uniform vec2 u_bottomLeft;
+ uniform vec2 u_bottomRight;
+
+ varying vec2 v_textureCoordinate;
+ varying vec4 v_color;
+
+ float xross(in vec2 a, in vec2 b) {
+ return a.x * b.y - a.y * b.x;
+ }
+
+ vec2 invBilinear(in vec2 p, in vec2 a, in vec2 b, in vec2 c, in vec2 d ){
+ vec2 e = b-a;
+ vec2 f = d-a;
+ vec2 g = a-b+c-d;
+ vec2 h = p-a;
+
+ float k2 = xross(g, f);
+ float k1 = xross(e, f) + xross(h, g);
+ float k0 = xross(h, e);
+
+ float w = k1*k1 - 4.0*k0*k2;
+
+ if( w<0.0 ) return vec2(-1.0);
+
+ w = sqrt(w);
+
+ // will fail for k0=0, which is only on the ba edge
+ float v = 2.0*k0/(-k1 - w);
+ if( v<0.0 || v>1.0 ) v = 2.0*k0/(-k1 + w);
+
+ float u = (h.x - f.x*v)/(e.x + g.x*v);
+ if( u<0.0 || u>1.0 || v<0.0 || v>1.0 ) return vec2(-1.0);
+ return vec2( u, v );
+ }
+
+ void main(void){
+ vec4 color = vec4(0.0);
+ vec2 texUv = invBilinear(v_textureCoordinate, u_topLeft, u_topRight, u_bottomRight, u_bottomLeft);
+
+ if (texUv.x > -0.5) {
+ color = texture2D(u_texture, texUv) * v_color;
+ }
+
+ gl_FragColor = color;
+ }
+ `,
+ };
+}
diff --git a/docs/example-projects/custom-shader-effect-texture/src/MyCustomTexture.ts b/docs/example-projects/custom-shader-effect-texture/src/MyCustomTexture.ts
new file mode 100644
index 00000000..f4044c4c
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/src/MyCustomTexture.ts
@@ -0,0 +1,72 @@
+import {
+ Texture,
+ type TextureData,
+ CoreTextureManager,
+} from '@lightningjs/renderer';
+import { assertTruthy } from '@lightningjs/renderer/utils';
+/**
+ * Augment the EffectMap interface to include the CustomEffect
+ */
+declare module '@lightningjs/renderer' {
+ interface TextureMap {
+ MyCustomTexture: typeof MyCustomTexture;
+ }
+}
+
+export interface MyCustomTextureProps {
+ percent?: number;
+ width: number;
+ height: number;
+}
+
+export class MyCustomTexture extends Texture {
+ static z$__type__Props: MyCustomTextureProps;
+
+ private props: Required;
+
+ constructor(txManager: CoreTextureManager, props: MyCustomTextureProps) {
+ super(txManager);
+ this.props = MyCustomTexture.resolveDefaults(props);
+ }
+
+ override async getTextureData(): Promise {
+ const { percent, width, height } = this.props;
+ const radius = Math.min(width, height) / 2;
+ const angle = 2 * Math.PI * (percent / 100);
+ const canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ const ctx = canvas.getContext('2d');
+ assertTruthy(ctx);
+ ctx.beginPath();
+ ctx.arc(radius, radius, radius, 0, 2 * Math.PI);
+ ctx.fillStyle = 'orange';
+ ctx.fill();
+ ctx.beginPath();
+ ctx.moveTo(radius, radius);
+ ctx.arc(radius, radius, radius, -angle / 2, angle / 2);
+ ctx.closePath();
+ ctx.fillStyle = 'blue';
+ ctx.fill();
+ return {
+ data: ctx.getImageData(0, 0, canvas.width, canvas.height),
+ };
+ }
+
+ static override makeCacheKey(props: MyCustomTextureProps): string | false {
+ // // Cache by props (only do this if could be helpful, otherwise leave it uncached)
+ // const rprops = MyCustomTexture.resolveDefaults(props)
+ // return `MyCustomTexture,${rprops.percent},${rprops.width},${rprops.height},`;
+ return false; // <-- Don't cache at all
+ }
+
+ static override resolveDefaults(
+ props: MyCustomTextureProps,
+ ): Required {
+ return {
+ percent: props.percent ?? 20,
+ width: props.width,
+ height: props.height,
+ };
+ }
+}
diff --git a/docs/example-projects/custom-shader-effect-texture/src/assets/robot.png b/docs/example-projects/custom-shader-effect-texture/src/assets/robot.png
new file mode 100644
index 00000000..e8befeb5
Binary files /dev/null and b/docs/example-projects/custom-shader-effect-texture/src/assets/robot.png differ
diff --git a/docs/example-projects/custom-shader-effect-texture/src/index.ts b/docs/example-projects/custom-shader-effect-texture/src/index.ts
new file mode 100644
index 00000000..46fbd3cd
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/src/index.ts
@@ -0,0 +1,71 @@
+import { RendererMain } from '@lightningjs/renderer';
+import { MyCustomEffect } from './MyCustomEffect.js';
+import { MyCustomShader } from './MyCustomShader.js';
+import { MyCustomTexture } from './MyCustomTexture.js';
+import robotImg from './assets/robot.png';
+
+(async () => {
+ const renderer = new RendererMain(
+ {
+ appWidth: 1920,
+ appHeight: 1080,
+ boundsMargin: [100, 100, 100, 100],
+ clearColor: 0x000000ff,
+ fpsUpdateInterval: 1000,
+ enableContextSpy: false,
+ enableInspector: false,
+ renderMode: 'webgl',
+ },
+ 'app',
+ );
+
+ renderer.stage.shManager.registerShaderType('MyCustomShader', MyCustomShader);
+ renderer.stage.shManager.registerEffectType('MyCustomEffect', MyCustomEffect);
+ renderer.stage.txManager.registerTextureType(
+ 'MyCustomTexture',
+ MyCustomTexture,
+ );
+
+ const distortedBot = renderer.createNode({
+ width: 300,
+ height: 300,
+ src: robotImg,
+ parent: renderer.root,
+ shader: renderer.createShader('MyCustomShader', {
+ normalized: true,
+ topLeft: { x: 0.5, y: 0 },
+ topRight: { x: 0.500001, y: 0 },
+ bottomRight: { x: 1, y: 1 },
+ bottomLeft: { x: 0, y: 1 },
+ }),
+ });
+
+ const greyRobot = renderer.createNode({
+ x: 300,
+ width: 300,
+ height: 300,
+ parent: renderer.root,
+ shader: renderer.createDynamicShader([
+ renderer.createEffect(
+ 'MyCustomEffect',
+ {
+ amount: 1.0,
+ },
+ 'custom',
+ ),
+ ]),
+ src: robotImg,
+ });
+
+ const pacman = renderer.createNode({
+ x: 600,
+ width: 300,
+ height: 300,
+ texture: renderer.createTexture('MyCustomTexture', {
+ percent: 5,
+ width: 300,
+ height: 300,
+ }),
+ parent: renderer.root,
+ });
+})().catch(console.error);
diff --git a/examples/common/CoreWorker.ts b/docs/example-projects/custom-shader-effect-texture/src/vite-env.d.ts
similarity index 86%
rename from examples/common/CoreWorker.ts
rename to docs/example-projects/custom-shader-effect-texture/src/vite-env.d.ts
index b0200772..77dd71a8 100644
--- a/examples/common/CoreWorker.ts
+++ b/docs/example-projects/custom-shader-effect-texture/src/vite-env.d.ts
@@ -17,4 +17,5 @@
* limitations under the License.
*/
-import '@lightningjs/renderer/workers/renderer';
+///
+// This enables Vite's import.meta augmentations and possibly other things?
diff --git a/docs/example-projects/custom-shader-effect-texture/tsconfig.cfg.json b/docs/example-projects/custom-shader-effect-texture/tsconfig.cfg.json
new file mode 100644
index 00000000..e8c9185d
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/tsconfig.cfg.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "outDir": "dist-cfg",
+ "types": ["@types/node"],
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "node",
+ "composite": true,
+ "resolveJsonModule": true,
+ "allowJs": true,
+ "esModuleInterop": true,
+ },
+ "files": [
+ "./vite.config.ts",
+ ]
+}
diff --git a/docs/example-projects/custom-shader-effect-texture/tsconfig.json b/docs/example-projects/custom-shader-effect-texture/tsconfig.json
new file mode 100644
index 00000000..3893d2a3
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/tsconfig.json
@@ -0,0 +1,33 @@
+{
+ "compilerOptions": {
+ "rootDir": ".",
+ "types": [],
+ "lib": ["ES2022", "DOM"],
+ "outDir": "dist-tsc",
+ "target": "ES2022",
+ "module": "Node16",
+ "moduleResolution": "Node16",
+ "sourceMap": true,
+ "declaration": true,
+ "experimentalDecorators": true,
+
+ // Type Checking / Syntax Rules
+ "strict": true,
+ "noUncheckedIndexedAccess": true,
+ "noImplicitOverride": true,
+ "allowSyntheticDefaultImports": true,
+ "resolveJsonModule": true,
+ "verbatimModuleSyntax": true,
+ "composite": true,
+ },
+ "include": [
+ "./src/**/*.ts"
+ ],
+ "exclude": ["node_modules", "./**/*.test.ts"],
+ "references": [
+ {
+ "path": "./tsconfig.cfg.json"
+ }
+ ],
+}
+
diff --git a/docs/example-projects/custom-shader-effect-texture/vite.config.ts b/docs/example-projects/custom-shader-effect-texture/vite.config.ts
new file mode 100644
index 00000000..2e2acacc
--- /dev/null
+++ b/docs/example-projects/custom-shader-effect-texture/vite.config.ts
@@ -0,0 +1,75 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2024 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineConfig } from 'vite';
+import * as path from 'path';
+
+/**
+ * Targeting ES2019 gets us at least to WPE 2.28
+ *
+ * Despite setting the target in different places in the Vite config below
+ * this does not seem to have an effect on the output when running Vite in
+ * development mode (`pnpm start`). In order to properly test on embedded devices
+ * that require the es2019 target, you must run `pnpm run build` and then serve the
+ * production build via `pnpm run preview`.
+ *
+ * See the following for any updates on this:
+ * https://github.com/vitejs/vite/issues/13756#issuecomment-1751085158
+ */
+const prodTarget = 'es2019';
+
+/**
+ * esbuild target for development mode
+ *
+ * Must be at least ES2020 to `import.meta.glob` to work. Even though this target
+ * mainly affects the output for the Vite dev server, it still affects how the
+ * `import.meta.glob` is transpiled in the production output.
+ */
+const devTarget = 'es2020';
+
+/**
+ * Vite Config
+ */
+export default defineConfig(({ command, mode }) => {
+ return {
+ worker: {
+ format: 'es',
+ },
+ esbuild: {
+ target: devTarget,
+ },
+ optimizeDeps: {
+ esbuildOptions: {
+ target: devTarget,
+ },
+ },
+ build: {
+ target: prodTarget,
+ minify: false,
+ sourcemap: true,
+ outDir: path.resolve(__dirname, 'dist'),
+ },
+ server: {
+ headers: {
+ 'Cross-Origin-Opener-Policy': 'same-origin',
+ 'Cross-Origin-Embedder-Policy': 'require-corp',
+ },
+ },
+ };
+});
diff --git a/examples/README.md b/examples/README.md
index 51a27361..93e5db01 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -44,6 +44,8 @@ pnpm watch
- `overlay` (boolean, default: "true")
- Whether or not to show the text overlay in the bottom-right corner that
displays the current test and driver being used.
+- `monitor` (boolean, default: "false")
+ - Whether or not to show the Texture Memory Monitor overlay.
- `resolution` (number, default: 720)
- Resolution (height) of to render the test at (in logical pixels)
- `fps` (boolean, default: "false")
diff --git a/examples/common/AppCoreExtension.ts b/examples/common/AppCoreExtension.ts
deleted file mode 100644
index 480877a1..00000000
--- a/examples/common/AppCoreExtension.ts
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * If not stated otherwise in this file or this component's LICENSE file the
- * following copyright and licenses apply:
- *
- * Copyright 2023 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import {
- CoreExtension,
- WebTrFontFace,
- type Stage,
- SdfTrFontFace,
- type FontMetrics,
-} from '@lightningjs/renderer/core';
-
-export default class AppCoreExtension extends CoreExtension {
- override async run(stage: Stage) {
- stage.fontManager.addFontFace(
- new WebTrFontFace({
- fontFamily: 'NotoSans',
- descriptors: {},
- fontUrl: '/fonts/NotoSans-Regular.ttf',
- metrics: {
- ascender: 1069,
- descender: -293,
- lineGap: 0,
- unitsPerEm: 1000,
- },
- }),
- );
-
- stage.fontManager.addFontFace(
- new WebTrFontFace({
- fontFamily: 'Ubuntu',
- descriptors: {},
- fontUrl: '/fonts/Ubuntu-Regular.ttf',
- metrics: {
- ascender: 776,
- descender: -185,
- lineGap: 56,
- unitsPerEm: 1000,
- },
- }),
- );
-
- stage.fontManager.addFontFace(
- new WebTrFontFace({
- fontFamily: 'Ubuntu-No-Metrics',
- descriptors: {},
- fontUrl: '/fonts/Ubuntu-Regular.ttf',
- }),
- );
-
- const ubuntuModifiedMetrics: FontMetrics = {
- ascender: 850,
- descender: -250,
- lineGap: 60,
- unitsPerEm: 1000,
- };
-
- stage.fontManager.addFontFace(
- new WebTrFontFace({
- fontFamily: 'Ubuntu-Modified-Metrics',
- descriptors: {},
- fontUrl: '/fonts/Ubuntu-Regular.ttf',
- metrics: ubuntuModifiedMetrics,
- }),
- );
-
- if (stage.renderer.mode === 'webgl') {
- stage.fontManager.addFontFace(
- new SdfTrFontFace('ssdf', {
- fontFamily: 'NotoSans',
- descriptors: {},
- atlasUrl: '/fonts/NotoSans-Regular.ssdf.png',
- atlasDataUrl: '/fonts/NotoSans-Regular.ssdf.json',
- stage,
- metrics: {
- ascender: 1000,
- descender: -200,
- lineGap: 0,
- unitsPerEm: 1000,
- },
- }),
- );
-
- stage.fontManager.addFontFace(
- new SdfTrFontFace('msdf', {
- fontFamily: 'Ubuntu',
- descriptors: {},
- atlasUrl: '/fonts/Ubuntu-Regular.msdf.png',
- atlasDataUrl: '/fonts/Ubuntu-Regular.msdf.json',
- stage,
- // Instead of suppling `metrics` this font will rely on the ones
- // encoded in the json file under `lightningMetrics`.
- }),
- );
-
- stage.fontManager.addFontFace(
- new SdfTrFontFace('msdf', {
- fontFamily: 'Ubuntu-Modified-Metrics',
- descriptors: {},
- atlasUrl: '/fonts/Ubuntu-Regular.msdf.png',
- atlasDataUrl: '/fonts/Ubuntu-Regular.msdf.json',
- stage,
- metrics: ubuntuModifiedMetrics,
- }),
- );
-
- stage.fontManager.addFontFace(
- new SdfTrFontFace('ssdf', {
- fontFamily: 'Ubuntu-ssdf',
- descriptors: {},
- atlasUrl: '/fonts/Ubuntu-Regular.ssdf.png',
- atlasDataUrl: '/fonts/Ubuntu-Regular.ssdf.json',
- stage,
- metrics: {
- ascender: 776,
- descender: -185,
- lineGap: 56,
- unitsPerEm: 1000,
- },
- }),
- );
- }
- }
-}
diff --git a/examples/common/Character.ts b/examples/common/Character.ts
index a84a765b..ee35dce6 100644
--- a/examples/common/Character.ts
+++ b/examples/common/Character.ts
@@ -18,11 +18,10 @@
*/
import type {
- SpecificTextureRef,
INode,
- INodeWritableProps,
+ INodeProps,
RendererMain,
- TextureRef,
+ TextureMap,
} from '@lightningjs/renderer';
import { assertTruthy } from '@lightningjs/renderer/utils';
@@ -31,12 +30,11 @@ export class Character {
curIntervalAnimation: ReturnType | null = null;
direction!: 'left' | 'right'; // Set in setState
state!: 'idle' | 'walk' | 'run' | 'jump'; // Set in setState
- leftFrames: TextureRef[] = [];
constructor(
- private props: Partial,
+ private props: Partial,
private renderer: RendererMain,
- private rightFrames: SpecificTextureRef<'SubTexture'>[],
+ private rightFrames: InstanceType[],
) {
this.node = renderer.createNode({
x: props.x,
@@ -47,11 +45,6 @@ export class Character {
parent: renderer.root,
zIndex: props.zIndex,
});
- this.leftFrames = rightFrames.map((frame) => {
- return renderer.createTexture('SubTexture', frame.props, {
- flipX: true,
- });
- });
assertTruthy(this.node);
this.setState('right', 'idle');
}
@@ -88,8 +81,8 @@ export class Character {
intervalMs: number,
) {
let curI = iStart;
- const frameArr = direction === 'left' ? this.leftFrames : this.rightFrames;
- if (iEnd + 1 > frameArr.length || iStart < 0) {
+ const flipX = direction === 'left' ? true : false;
+ if (iEnd + 1 > this.rightFrames.length || iStart < 0) {
throw new Error('Animation out of bounds');
}
if (this.curIntervalAnimation) {
@@ -97,7 +90,8 @@ export class Character {
}
const nextFrame = () => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.node.texture = frameArr[curI]!;
+ this.node.texture = this.rightFrames[curI]!;
+ this.node.textureOptions.flipX = flipX;
curI++;
if (curI > iEnd) {
curI = iStart;
diff --git a/examples/common/Component.ts b/examples/common/Component.ts
index 8b02d499..3990dcca 100644
--- a/examples/common/Component.ts
+++ b/examples/common/Component.ts
@@ -17,19 +17,12 @@
* limitations under the License.
*/
-import type {
- INode,
- INodeWritableProps,
- RendererMain,
-} from '@lightningjs/renderer';
+import type { INode, INodeProps, RendererMain } from '@lightningjs/renderer';
export class Component {
readonly node: INode;
- constructor(
- readonly renderer: RendererMain,
- nodeProps: Partial,
- ) {
+ constructor(readonly renderer: RendererMain, nodeProps: Partial) {
this.node = renderer.createNode({
...nodeProps,
});
diff --git a/examples/common/ExampleSettings.ts b/examples/common/ExampleSettings.ts
index 755bd00d..a2ef140c 100644
--- a/examples/common/ExampleSettings.ts
+++ b/examples/common/ExampleSettings.ts
@@ -18,6 +18,7 @@
*/
import type { INode, RendererMain } from '@lightningjs/renderer';
+import type { MemMonitor } from './MemMonitor.js';
/**
* Keep in sync with `visual-regression/src/index.ts`
@@ -51,10 +52,6 @@ export interface ExampleSettings {
* Renderer instance
*/
renderer: RendererMain;
- /**
- * Core Driver being used by the test.
- */
- driverName: 'main' | 'threadx';
/**
* The HTML Element that the Renderer's canvas is a child of
*/
@@ -87,4 +84,8 @@ export interface ExampleSettings {
* This method will be a no-op if the test is not run in automation mode.
*/
snapshot(options?: SnapshotOptions): Promise;
+ /**
+ * The MemMonitor instance for the test (if enabled)
+ */
+ memMonitor: MemMonitor | null;
}
diff --git a/examples/common/MemMonitor.ts b/examples/common/MemMonitor.ts
new file mode 100644
index 00000000..03b62076
--- /dev/null
+++ b/examples/common/MemMonitor.ts
@@ -0,0 +1,267 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type {
+ INode,
+ INodeProps,
+ ITextNode,
+ RendererMain,
+} from '@lightningjs/renderer';
+import { Component } from './Component.js';
+
+const MARGIN = 20;
+const BAR_WIDTH = 20;
+const BAR_HEIGHT = 300;
+const INFO_TEXT_SIZE = 20;
+const INFO_TEXT_LINEHEIGHT = INFO_TEXT_SIZE * 1.2;
+
+function bytesToMb(bytes: number) {
+ return (bytes / 1024 / 1024).toFixed(2);
+}
+
+export interface MemMonitorProps extends Partial {
+ interval?: number;
+}
+
+export class MemMonitor extends Component {
+ // private memTextNode: ITextNode;
+ private bar: INode;
+ private renderableMemBar: INode;
+ private memUsedBar: INode;
+ private criticalText: ITextNode;
+ private criticalTick: INode;
+ private targetText: ITextNode;
+ private targetTick: INode;
+ private criticalInfoText: ITextNode;
+ private targetInfoText: ITextNode;
+ private memUsedText: ITextNode;
+ private renderableMemUsedText: ITextNode;
+ private cacheInfoText: ITextNode;
+ private intervalHandle: NodeJS.Timeout | null = null;
+ private _interval = 0;
+
+ constructor(renderer: RendererMain, props: MemMonitorProps) {
+ super(renderer, props);
+
+ this.interval = props.interval || 500;
+ this.node.color = 0xffffffaa;
+ this.node.width = 400;
+ this.node.height = BAR_HEIGHT + MARGIN * 2;
+
+ this.bar = renderer.createNode({
+ x: this.node.width - BAR_WIDTH - MARGIN,
+ y: MARGIN,
+ width: BAR_WIDTH,
+ height: BAR_HEIGHT,
+ parent: this.node,
+ color: 0x00000000,
+ });
+
+ this.memUsedBar = renderer.createNode({
+ x: 0,
+ y: 0,
+ width: BAR_WIDTH,
+ height: 0,
+ parent: this.bar,
+ color: 0x0000ffff,
+ });
+
+ this.renderableMemBar = renderer.createNode({
+ x: 0,
+ y: 0,
+ width: BAR_WIDTH,
+ height: 0,
+ parent: this.bar,
+ color: 0xff00ffff,
+ });
+
+ // Bar Frame
+ renderer.createNode({
+ width: BAR_WIDTH,
+ height: BAR_HEIGHT,
+ rtt: true,
+ shader: renderer.createShader('DynamicShader', {
+ effects: [
+ {
+ name: 'e1',
+ type: 'border',
+ props: {
+ color: 0x000000cc,
+ width: 4,
+ },
+ },
+ ],
+ }),
+ parent: this.bar,
+ });
+
+ this.criticalText = renderer.createTextNode({
+ x: -15,
+ y: 0,
+ text: 'Critical',
+ fontFamily: 'Ubuntu',
+ parent: this.bar,
+ fontSize: 20,
+ color: 0xff0000ff,
+ mountX: 1,
+ mountY: 0.5,
+ });
+
+ this.criticalTick = renderer.createNode({
+ x: BAR_WIDTH / 2,
+ y: 0,
+ width: BAR_WIDTH * 2,
+ height: 2,
+ parent: this.bar,
+ color: 0xff0000ff,
+ mount: 0.5,
+ });
+
+ this.targetText = renderer.createTextNode({
+ x: -15,
+ y: 0,
+ text: 'Target',
+ fontFamily: 'Ubuntu',
+ parent: this.bar,
+ fontSize: 20,
+ color: 0x000000ff,
+ mountX: 1,
+ mountY: 0.5,
+ });
+
+ this.targetTick = renderer.createNode({
+ x: BAR_WIDTH / 2,
+ y: 0,
+ width: BAR_WIDTH * 2,
+ height: 2,
+ parent: this.bar,
+ color: 0x000000ff,
+ mount: 0.5,
+ });
+
+ const numLines = 9;
+ const infoTextY =
+ this.node.height - MARGIN - INFO_TEXT_LINEHEIGHT * numLines;
+
+ this.criticalInfoText = renderer.createTextNode({
+ x: MARGIN,
+ y: infoTextY,
+ text: '',
+ fontFamily: 'Ubuntu',
+ parent: this.node,
+ fontSize: INFO_TEXT_SIZE,
+ lineHeight: INFO_TEXT_LINEHEIGHT,
+ color: 0xff0000ff,
+ });
+
+ this.targetInfoText = renderer.createTextNode({
+ x: MARGIN,
+ y: infoTextY + INFO_TEXT_LINEHEIGHT,
+ text: '',
+ fontFamily: 'Ubuntu',
+ parent: this.node,
+ fontSize: INFO_TEXT_SIZE,
+ lineHeight: INFO_TEXT_LINEHEIGHT,
+ color: 0x000000ff,
+ });
+
+ this.memUsedText = renderer.createTextNode({
+ x: MARGIN,
+ y: infoTextY + INFO_TEXT_LINEHEIGHT * 2,
+ text: '',
+ fontFamily: 'Ubuntu',
+ parent: this.node,
+ fontSize: INFO_TEXT_SIZE,
+ lineHeight: INFO_TEXT_LINEHEIGHT,
+ color: 0x0000ffff,
+ });
+
+ this.renderableMemUsedText = renderer.createTextNode({
+ x: MARGIN,
+ y: infoTextY + INFO_TEXT_LINEHEIGHT * 5,
+ text: '',
+ fontFamily: 'Ubuntu',
+ parent: this.node,
+ fontSize: INFO_TEXT_SIZE,
+ lineHeight: INFO_TEXT_LINEHEIGHT,
+ color: 0xff00ffff,
+ });
+
+ this.cacheInfoText = renderer.createTextNode({
+ x: MARGIN,
+ y: infoTextY + INFO_TEXT_LINEHEIGHT * 8,
+ text: '',
+ fontFamily: 'Ubuntu',
+ parent: this.node,
+ fontSize: INFO_TEXT_SIZE,
+ lineHeight: INFO_TEXT_LINEHEIGHT,
+ color: 0x000000ff,
+ });
+
+ const payload = this.renderer.stage.txMemManager.getMemoryInfo();
+ const { criticalThreshold, targetThreshold } = payload;
+ const targetFraction = targetThreshold / criticalThreshold;
+ this.targetTick.y = BAR_HEIGHT - BAR_HEIGHT * targetFraction;
+ this.targetText.y = this.targetTick.y;
+ this.targetInfoText.text = `Target: ${bytesToMb(targetThreshold)} mb (${(
+ targetFraction * 100
+ ).toFixed(1)}%)`;
+ this.criticalInfoText.text = `Critical: ${bytesToMb(criticalThreshold)} mb`;
+
+ this.update();
+ }
+
+ update() {
+ const payload = this.renderer.stage.txMemManager.getMemoryInfo();
+ const { criticalThreshold, memUsed, renderableMemUsed } = payload;
+ const renderableMemoryFraction = renderableMemUsed / criticalThreshold;
+ const memUsedFraction = memUsed / criticalThreshold;
+ this.memUsedBar.height = BAR_HEIGHT * memUsedFraction;
+ this.renderableMemBar.height = BAR_HEIGHT * renderableMemoryFraction;
+ this.renderableMemBar.y = BAR_HEIGHT - this.renderableMemBar.height;
+ this.memUsedBar.y = BAR_HEIGHT - this.memUsedBar.height;
+ this.memUsedText.text = `
+Textures Loaded
+- Size: ${bytesToMb(memUsed)} mb (${(memUsedFraction * 100).toFixed(1)}%)
+- Count: ${payload.loadedTextures}
+`.trim();
+ this.renderableMemUsedText.text = `
+Renderable Loaded
+- ${bytesToMb(renderableMemUsed)} mb (${(
+ renderableMemoryFraction * 100
+ ).toFixed(1)}%)
+- Count: ${payload.renderableTexturesLoaded}
+`.trim();
+ this.cacheInfoText.text = `Cache Size: ${this.renderer.stage.txManager.keyCache.size}`;
+ }
+
+ get interval() {
+ return this._interval;
+ }
+
+ set interval(interval) {
+ this._interval = interval;
+ if (this.intervalHandle) {
+ clearInterval(this.intervalHandle);
+ }
+ this.intervalHandle = setInterval(() => {
+ this.update();
+ }, this._interval);
+ }
+}
diff --git a/examples/common/PageContainer.ts b/examples/common/PageContainer.ts
index 5bb78d71..2165d6a2 100644
--- a/examples/common/PageContainer.ts
+++ b/examples/common/PageContainer.ts
@@ -17,7 +17,7 @@
* limitations under the License.
*/
-import type { INode, ITextNode, RendererMain } from '@lightningjs/renderer';
+import type { INode, ITextNode } from '@lightningjs/renderer';
import { Component } from './Component.js';
import { loadStorage, saveStorage } from '../common/LocalStorage.js';
import type { ExampleSettings } from './ExampleSettings.js';
diff --git a/examples/common/constructTestRow.ts b/examples/common/constructTestRow.ts
index a814fd93..d5e88526 100644
--- a/examples/common/constructTestRow.ts
+++ b/examples/common/constructTestRow.ts
@@ -17,7 +17,7 @@
* limitations under the License.
*/
-import type { INode, RendererMain } from '../../dist/exports/main-api.js';
+import type { INode, RendererMain } from '@lightningjs/renderer';
import { waitForLoadedDimensions } from './utils.js';
const CONTAINER_SIZE = 200;
diff --git a/examples/common/installFonts.ts b/examples/common/installFonts.ts
new file mode 100644
index 00000000..a5dbf617
--- /dev/null
+++ b/examples/common/installFonts.ts
@@ -0,0 +1,136 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ WebTrFontFace,
+ type Stage,
+ SdfTrFontFace,
+ type FontMetrics,
+} from '@lightningjs/renderer';
+
+export function installFonts(stage: Stage) {
+ stage.fontManager.addFontFace(
+ new WebTrFontFace({
+ fontFamily: 'NotoSans',
+ descriptors: {},
+ fontUrl: '/fonts/NotoSans-Regular.ttf',
+ metrics: {
+ ascender: 1069,
+ descender: -293,
+ lineGap: 0,
+ unitsPerEm: 1000,
+ },
+ }),
+ );
+
+ stage.fontManager.addFontFace(
+ new WebTrFontFace({
+ fontFamily: 'Ubuntu',
+ descriptors: {},
+ fontUrl: '/fonts/Ubuntu-Regular.ttf',
+ metrics: {
+ ascender: 776,
+ descender: -185,
+ lineGap: 56,
+ unitsPerEm: 1000,
+ },
+ }),
+ );
+
+ stage.fontManager.addFontFace(
+ new WebTrFontFace({
+ fontFamily: 'Ubuntu-No-Metrics',
+ descriptors: {},
+ fontUrl: '/fonts/Ubuntu-Regular.ttf',
+ }),
+ );
+
+ const ubuntuModifiedMetrics: FontMetrics = {
+ ascender: 850,
+ descender: -250,
+ lineGap: 60,
+ unitsPerEm: 1000,
+ };
+
+ stage.fontManager.addFontFace(
+ new WebTrFontFace({
+ fontFamily: 'Ubuntu-Modified-Metrics',
+ descriptors: {},
+ fontUrl: '/fonts/Ubuntu-Regular.ttf',
+ metrics: ubuntuModifiedMetrics,
+ }),
+ );
+
+ if (stage.renderer.mode === 'webgl') {
+ stage.fontManager.addFontFace(
+ new SdfTrFontFace('ssdf', {
+ fontFamily: 'NotoSans',
+ descriptors: {},
+ atlasUrl: '/fonts/NotoSans-Regular.ssdf.png',
+ atlasDataUrl: '/fonts/NotoSans-Regular.ssdf.json',
+ stage,
+ metrics: {
+ ascender: 1000,
+ descender: -200,
+ lineGap: 0,
+ unitsPerEm: 1000,
+ },
+ }),
+ );
+
+ stage.fontManager.addFontFace(
+ new SdfTrFontFace('msdf', {
+ fontFamily: 'Ubuntu',
+ descriptors: {},
+ atlasUrl: '/fonts/Ubuntu-Regular.msdf.png',
+ atlasDataUrl: '/fonts/Ubuntu-Regular.msdf.json',
+ stage,
+ // Instead of suppling `metrics` this font will rely on the ones
+ // encoded in the json file under `lightningMetrics`.
+ }),
+ );
+
+ stage.fontManager.addFontFace(
+ new SdfTrFontFace('msdf', {
+ fontFamily: 'Ubuntu-Modified-Metrics',
+ descriptors: {},
+ atlasUrl: '/fonts/Ubuntu-Regular.msdf.png',
+ atlasDataUrl: '/fonts/Ubuntu-Regular.msdf.json',
+ stage,
+ metrics: ubuntuModifiedMetrics,
+ }),
+ );
+
+ stage.fontManager.addFontFace(
+ new SdfTrFontFace('ssdf', {
+ fontFamily: 'Ubuntu-ssdf',
+ descriptors: {},
+ atlasUrl: '/fonts/Ubuntu-Regular.ssdf.png',
+ atlasDataUrl: '/fonts/Ubuntu-Regular.ssdf.json',
+ stage,
+ metrics: {
+ ascender: 776,
+ descender: -185,
+ lineGap: 56,
+ unitsPerEm: 1000,
+ },
+ }),
+ );
+ }
+}
diff --git a/examples/common/paginateTestRows.ts b/examples/common/paginateTestRows.ts
index d9847306..a2eb6eb4 100644
--- a/examples/common/paginateTestRows.ts
+++ b/examples/common/paginateTestRows.ts
@@ -18,8 +18,8 @@
*/
import type { INode } from '@lightningjs/renderer';
-import { PageContainer } from './PageContainer.js';
import { assertTruthy } from '@lightningjs/renderer/utils';
+import { PageContainer } from './PageContainer.js';
const HEADER_FONT_SIZE = 30;
const PADDING = 20;
diff --git a/examples/common/utils.ts b/examples/common/utils.ts
index ca307708..1586674f 100644
--- a/examples/common/utils.ts
+++ b/examples/common/utils.ts
@@ -19,9 +19,9 @@
import type {
Dimensions,
- ITextNode,
- INode,
NodeTextLoadedPayload,
+ INode,
+ ITextNode,
} from '@lightningjs/renderer';
export async function waitForLoadedDimensions(
diff --git a/examples/index.ts b/examples/index.ts
index 120d7508..6a9ffab3 100644
--- a/examples/index.ts
+++ b/examples/index.ts
@@ -18,23 +18,20 @@
*/
import {
- MainCoreDriver,
RendererMain,
- ThreadXCoreDriver,
- type ICoreDriver,
type NodeLoadedPayload,
type RendererMainSettings,
type FpsUpdatePayload,
} from '@lightningjs/renderer';
import { assertTruthy } from '@lightningjs/renderer/utils';
import * as mt19937 from '@stdlib/random-base-mt19937';
-import coreWorkerUrl from './common/CoreWorker.js?importChunkUrl';
-import coreExtensionModuleUrl from './common/AppCoreExtension.js?importChunkUrl';
import type {
ExampleSettings,
SnapshotOptions,
} from './common/ExampleSettings.js';
import { StatTracker } from './common/StatTracker.js';
+import { installFonts } from './common/installFonts.js';
+import { MemMonitor } from './common/MemMonitor.js';
interface TestModule {
default: (settings: ExampleSettings) => Promise;
@@ -75,6 +72,7 @@ const defaultPhysicalPixelRatio = 1;
*/
const test = urlParams.get('test') || (automation ? '*' : 'test');
const showOverlay = urlParams.get('overlay') !== 'false';
+ const showMemMonitor = urlParams.get('monitor') === 'true';
const logFps = urlParams.get('fps') === 'true';
const enableContextSpy = urlParams.get('contextSpy') === 'true';
const perfMultiplier = Number(urlParams.get('multiplier')) || 1;
@@ -84,26 +82,18 @@ const defaultPhysicalPixelRatio = 1;
Number(urlParams.get('ppr')) || defaultPhysicalPixelRatio;
const logicalPixelRatio = resolution / appHeight;
- let driverName = urlParams.get('driver');
- if (driverName !== 'main' && driverName !== 'threadx') {
- driverName = 'main';
- }
-
let renderMode = urlParams.get('renderMode');
- if (
- driverName === 'threadx' ||
- (renderMode !== 'webgl' && renderMode !== 'canvas')
- ) {
+ if (renderMode !== 'webgl' && renderMode !== 'canvas') {
renderMode = 'webgl';
}
if (!automation) {
await runTest(
test,
- driverName,
renderMode,
urlParams,
showOverlay,
+ showMemMonitor,
logicalPixelRatio,
physicalPixelRatio,
logFps,
@@ -114,17 +104,17 @@ const defaultPhysicalPixelRatio = 1;
return;
}
assertTruthy(automation);
- await runAutomation(driverName, renderMode, test, logFps);
+ await runAutomation(renderMode, test, logFps);
})().catch((err) => {
console.error(err);
});
async function runTest(
test: string,
- driverName: string,
renderMode: string,
urlParams: URLSearchParams,
showOverlay: boolean,
+ showMemMonitor: boolean,
logicalPixelRatio: number,
physicalPixelRatio: number,
logFps: boolean,
@@ -146,7 +136,6 @@ async function runTest(
: {};
const { renderer, appElement } = await initRenderer(
- driverName,
renderMode,
logFps,
enableContextSpy,
@@ -156,10 +145,12 @@ async function runTest(
customSettings,
);
+ let testRoot = renderer.root;
+
if (showOverlay) {
const overlayText = renderer.createTextNode({
color: 0xff0000ff,
- text: `Test: ${test} | Driver: ${driverName}`,
+ text: `Test: ${test}`,
zIndex: 99999,
parent: renderer.root,
fontSize: 50,
@@ -173,18 +164,41 @@ async function runTest(
);
}
+ let memMonitor: MemMonitor | null = null;
+ if (showMemMonitor) {
+ memMonitor = new MemMonitor(renderer, {
+ mount: 1,
+ x: renderer.settings.appWidth - 20,
+ y: renderer.settings.appHeight - 100,
+ parent: renderer.root,
+ zIndex: 99999,
+ });
+ }
+
+ if (showOverlay || showMemMonitor) {
+ // If we're showing the overlay text or mem monitor, create a new root node
+ // for the test content so it doesn't interfere with the overlay.
+ testRoot = renderer.createNode({
+ parent: renderer.root,
+ x: renderer.root.x,
+ y: renderer.root.y,
+ width: renderer.settings.appWidth,
+ height: renderer.settings.appHeight - 100,
+ color: 0x00000000,
+ });
+ }
+
const exampleSettings: ExampleSettings = {
testName: test,
renderer,
- driverName: driverName as 'main' | 'threadx',
appElement,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- testRoot: renderer.root!,
+ testRoot,
automation: false,
perfMultiplier: perfMultiplier,
snapshot: async () => {
// No-op
},
+ memMonitor,
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
@@ -192,7 +206,6 @@ async function runTest(
}
async function initRenderer(
- driverName: string,
renderMode: string,
logFps: boolean,
enableContextSpy: boolean,
@@ -201,16 +214,6 @@ async function initRenderer(
enableInspector: boolean,
customSettings?: Partial,
) {
- let driver: ICoreDriver | null = null;
-
- if (driverName === 'main') {
- driver = new MainCoreDriver();
- } else {
- driver = new ThreadXCoreDriver({
- coreWorkerUrl,
- });
- }
-
const renderer = new RendererMain(
{
appWidth,
@@ -219,7 +222,6 @@ async function initRenderer(
deviceLogicalPixelRatio: logicalPixelRatio,
devicePhysicalPixelRatio: physicalPixelRatio,
clearColor: 0x00000000,
- coreExtensionModule: coreExtensionModuleUrl,
fpsUpdateInterval: logFps ? 1000 : 0,
enableContextSpy,
enableInspector,
@@ -227,8 +229,8 @@ async function initRenderer(
...customSettings,
},
'app',
- driver,
);
+ installFonts(renderer.stage);
/**
* Sample data captured
@@ -313,8 +315,6 @@ async function initRenderer(
},
);
- await renderer.init();
-
const appElement = document.querySelector('#app');
assertTruthy(appElement instanceof HTMLDivElement);
@@ -330,14 +330,12 @@ function wildcardMatch(string: string, wildcardString: string) {
}
async function runAutomation(
- driverName: string,
renderMode: string,
filter: string | null,
logFps: boolean,
) {
const logicalPixelRatio = defaultResolution / appHeight;
const { renderer, appElement } = await initRenderer(
- driverName,
renderMode,
logFps,
false,
@@ -383,7 +381,6 @@ async function runAutomation(
testName,
renderer,
testRoot,
- driverName: driverName as 'main' | 'threadx',
appElement,
automation: true,
perfMultiplier: 1,
@@ -421,6 +418,7 @@ async function runAutomation(
);
}
},
+ memMonitor: null,
};
await automation(exampleSettings);
testRoot.parent = null;
diff --git a/examples/package.json b/examples/package.json
index 64fde16b..26426e37 100644
--- a/examples/package.json
+++ b/examples/package.json
@@ -24,8 +24,7 @@
"@stdlib/random-base-mt19937": "^0.2.1"
},
"devDependencies": {
- "@lightningjs/vite-plugin-import-chunk-url": "^0.3.0",
- "vite": "^4.4.9"
+ "vite": "^5.0.0"
},
"engines": {
"npm": "please-use-pnpm"
diff --git a/examples/tests/clipping.ts b/examples/tests/clipping.ts
index 576e01d3..eb99d9f3 100644
--- a/examples/tests/clipping.ts
+++ b/examples/tests/clipping.ts
@@ -22,7 +22,7 @@ import { paginateTestRows } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
import { waitForLoadedDimensions } from '../common/utils.js';
import { deg2Rad } from '@lightningjs/renderer/utils';
-import type { INodeWritableProps } from '@lightningjs/renderer';
+import type { INodeProps } from '@lightningjs/renderer';
import robotImg from '../assets/robot/robot.png';
export async function automation(settings: ExampleSettings) {
@@ -492,7 +492,7 @@ export default async function test(settings: ExampleSettings) {
parent: rowNode,
color: 0x00ff00ff,
clipping: true,
- } satisfies Partial;
+ } satisfies Partial;
const clippingParentProps = {
mount: 0.5,
@@ -502,14 +502,14 @@ export default async function test(settings: ExampleSettings) {
height: SQUARE_SIZE / 2,
clipping: true,
// rotation: Math.PI / 4
- } satisfies Partial;
+ } satisfies Partial;
const clippingChildProps = {
width: SQUARE_SIZE,
height: SQUARE_SIZE,
mount: 0.5,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
const container = renderer.createNode({
...containerProps,
@@ -632,7 +632,7 @@ export default async function test(settings: ExampleSettings) {
parent: rowNode,
color: 0x00ff00ff,
clipping: true,
- } satisfies Partial;
+ } satisfies Partial;
const clippingParentProps = {
mount: 0.5,
@@ -641,14 +641,14 @@ export default async function test(settings: ExampleSettings) {
width: SQUARE_SIZE / 2,
height: SQUARE_SIZE / 2,
clipping: true,
- } satisfies Partial;
+ } satisfies Partial;
const clippingChildProps = {
width: SQUARE_SIZE,
height: SQUARE_SIZE,
mount: 0.5,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
const container = renderer.createNode({
...containerProps,
diff --git a/examples/tests/render-bounds.ts b/examples/tests/render-bounds.ts
index 7c88e2e0..6065c5d5 100644
--- a/examples/tests/render-bounds.ts
+++ b/examples/tests/render-bounds.ts
@@ -1,6 +1,5 @@
-import type { IAnimationController } from '../../dist/exports/main-api.js';
+import type { IAnimationController } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
-import test from './alpha-blending.js';
export default async function ({ renderer, testRoot }: ExampleSettings) {
const degToRad = (deg: number) => {
diff --git a/examples/tests/resize-mode.ts b/examples/tests/resize-mode.ts
index ed0ca47d..118884f4 100644
--- a/examples/tests/resize-mode.ts
+++ b/examples/tests/resize-mode.ts
@@ -20,7 +20,7 @@
import testscreenImg from '../assets/testscreen.png';
import testscreenRImg from '../assets/testscreen_rotated.png';
import type { ExampleSettings } from '../common/ExampleSettings.js';
-import type { INodeWritableProps } from '@lightningjs/renderer';
+import type { INodeProps } from '@lightningjs/renderer';
import { paginateTestRows } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
import { deg2Rad } from '../../dist/src/utils.js';
@@ -53,17 +53,16 @@ export default async function test(settings: ExampleSettings) {
x: curX,
width: SQUARE_SIZE,
height: SQUARE_SIZE - 300,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenImg },
- {
- resizeMode: {
- type: 'cover',
- clipY: [0, 0.5, 1][i],
- clipX: [0, 0.5, 1][i],
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'cover',
+ clipY: [0, 0.5, 1][i],
+ clipX: [0, 0.5, 1][i],
},
- ),
+ },
parent: rowNode,
});
curX += SQUARE_SIZE + PADDING;
@@ -84,17 +83,16 @@ export default async function test(settings: ExampleSettings) {
x: curX,
width: SQUARE_SIZE,
height: SQUARE_SIZE - 200,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenImg },
- {
- resizeMode: {
- type: 'cover',
- clipY: [0, 0.5, 1][i],
- clipX: [0, 0.5, 1][i],
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'cover',
+ clipY: [0, 0.5, 1][i],
+ clipX: [0, 0.5, 1][i],
},
- ),
+ },
parent: rowNode,
});
curX += SQUARE_SIZE + PADDING;
@@ -115,17 +113,16 @@ export default async function test(settings: ExampleSettings) {
x: curX,
width: SQUARE_SIZE,
height: SQUARE_SIZE - 300,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenRImg },
- {
- resizeMode: {
- type: 'cover',
- clipY: [0, 0.5, 1][i],
- clipX: [0, 0.5, 1][i],
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenRImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'cover',
+ clipY: [0, 0.5, 1][i],
+ clipX: [0, 0.5, 1][i],
},
- ),
+ },
parent: rowNode,
});
curX += SQUARE_SIZE + PADDING;
@@ -146,17 +143,16 @@ export default async function test(settings: ExampleSettings) {
x: curX,
width: SQUARE_SIZE - 400,
height: SQUARE_SIZE - 100,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenRImg },
- {
- resizeMode: {
- type: 'cover',
- clipX: [0, 0.25, 0.5, 0.75, 1][i],
- clipY: [0, 0.25, 0.5, 0.75, 1][i],
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenRImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'cover',
+ clipX: [0, 0.25, 0.5, 0.75, 1][i],
+ clipY: [0, 0.25, 0.5, 0.75, 1][i],
},
- ),
+ },
parent: rowNode,
});
curX += SQUARE_SIZE + PADDING - 330;
@@ -177,22 +173,21 @@ export default async function test(settings: ExampleSettings) {
parent: rowNode,
color: 0x333333ff,
clipping: true,
- } satisfies Partial;
+ } satisfies Partial;
const textureNodeProps = {
width: containerProps.width,
height: containerProps.height,
clipping: true,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenImg },
- {
- resizeMode: {
- type: 'contain',
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'contain',
},
- ),
- } satisfies Partial;
+ },
+ } satisfies Partial;
const container1 = renderer.createNode({
...containerProps,
@@ -221,22 +216,21 @@ export default async function test(settings: ExampleSettings) {
parent: rowNode,
color: 0x333333ff,
clipping: true,
- } satisfies Partial;
+ } satisfies Partial;
const textureNodeProps = {
width: containerProps.width,
height: containerProps.height,
clipping: true,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenImg },
- {
- resizeMode: {
- type: 'contain',
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'contain',
},
- ),
- } satisfies Partial;
+ },
+ } satisfies Partial;
const container1 = renderer.createNode({
...containerProps,
@@ -263,22 +257,21 @@ export default async function test(settings: ExampleSettings) {
parent: rowNode,
color: 0x333333ff,
clipping: true,
- } satisfies Partial;
+ } satisfies Partial;
const textureNodeProps = {
width: containerProps.width,
height: containerProps.height,
clipping: true,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenRImg },
- {
- resizeMode: {
- type: 'contain',
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenRImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'contain',
},
- ),
- } satisfies Partial;
+ },
+ } satisfies Partial;
const container1 = renderer.createNode({
...containerProps,
@@ -322,22 +315,21 @@ export default async function test(settings: ExampleSettings) {
parent: rowNode,
color: 0x333333ff,
clipping: true,
- } satisfies Partial;
+ } satisfies Partial;
const textureNodeProps = {
width: containerProps.width,
height: containerProps.height,
clipping: true,
- texture: renderer.createTexture(
- 'ImageTexture',
- { src: testscreenRImg },
- {
- resizeMode: {
- type: 'contain',
- },
+ texture: renderer.createTexture('ImageTexture', {
+ src: testscreenRImg,
+ }),
+ textureOptions: {
+ resizeMode: {
+ type: 'contain',
},
- ),
- } satisfies Partial;
+ },
+ } satisfies Partial;
const container1 = renderer.createNode({
...containerProps,
diff --git a/examples/tests/rtt-dimension.ts b/examples/tests/rtt-dimension.ts
index 02a36bf2..6965174e 100644
--- a/examples/tests/rtt-dimension.ts
+++ b/examples/tests/rtt-dimension.ts
@@ -185,6 +185,10 @@ export default async function test({ renderer, testRoot }: ExampleSettings) {
width: 100,
height: 100,
texture: nestedRTTNode1.texture,
+ // Flip every other one of them
+ textureOptions: {
+ flipY: i % 2 === 1,
+ },
});
}
diff --git a/examples/tests/scaling.ts b/examples/tests/scaling.ts
index 692cc54e..0afecfe4 100644
--- a/examples/tests/scaling.ts
+++ b/examples/tests/scaling.ts
@@ -16,11 +16,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+import type { INodeProps } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
-import type { INodeWritableProps } from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
import robotImg from '../assets/robot/robot.png';
@@ -51,7 +50,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -88,7 +87,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -125,7 +124,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -165,7 +164,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -202,7 +201,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -239,7 +238,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -279,7 +278,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -316,7 +315,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
@@ -353,7 +352,7 @@ export default async function test(settings: ExampleSettings) {
width: 100,
height: 100,
src: robotImg,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createNode({
diff --git a/examples/tests/shader-animation.ts b/examples/tests/shader-animation.ts
new file mode 100644
index 00000000..8109677f
--- /dev/null
+++ b/examples/tests/shader-animation.ts
@@ -0,0 +1,154 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { ExampleSettings } from '../common/ExampleSettings.js';
+
+export async function automation(settings: ExampleSettings) {
+ // Snapshot single page
+ await test(settings);
+ // await settings.snapshot();
+}
+
+export default async function test({
+ renderer,
+ testRoot,
+ snapshot,
+}: ExampleSettings) {
+ const degToRad = (deg: number) => {
+ return (Math.PI / 180) * deg;
+ };
+
+ const nodeSize = {
+ width: 300,
+ height: 300,
+ };
+
+ const t1 = renderer.createNode({
+ ...nodeSize,
+ x: 90,
+ y: 90,
+ color: 0xff0000ff,
+ shader: renderer.createShader('RoundedRectangle', {
+ radius: 100,
+ }),
+ parent: testRoot,
+ });
+
+ const t1Radius = renderer.createTextNode({
+ mountX: 1,
+ x: testRoot.width - 90,
+ y: 90,
+ fontSize: 40,
+ fontFamily: 'Ubuntu',
+ text: 'radius: 100',
+ parent: testRoot,
+ color: 0xffffffff,
+ });
+
+ const t2 = renderer.createNode({
+ ...nodeSize,
+ x: 90,
+ y: 540,
+ color: 0x00ff00ff,
+ shader: renderer.createDynamicShader([
+ renderer.createEffect(
+ 'radius',
+ {
+ radius: 0,
+ },
+ 'r1',
+ ),
+ renderer.createEffect(
+ 'border',
+ {
+ color: 0xff00ffff,
+ width: 10,
+ },
+ 'e1',
+ ),
+ ]),
+ parent: testRoot,
+ });
+
+ const t2Radius = renderer.createTextNode({
+ mountX: 1,
+ x: testRoot.width - 90,
+ y: 540,
+ fontSize: 40,
+ fontFamily: 'Ubuntu',
+ text: 'radius: 0',
+ parent: testRoot,
+ color: 0xffffffff,
+ });
+
+ const t2Border = renderer.createTextNode({
+ mountX: 1,
+ x: testRoot.width - 90,
+ y: 590,
+ fontSize: 40,
+ fontFamily: 'Ubuntu',
+ text: 'border: 10',
+ parent: testRoot,
+ color: 0xffffffff,
+ });
+
+ await snapshot({ name: 'startup' });
+
+ const shaderAnimation = t1.animate(
+ {
+ x: 1140,
+ shaderProps: {
+ radius: 150,
+ },
+ },
+ {
+ duration: 500,
+ },
+ );
+ shaderAnimation.start();
+ await shaderAnimation.waitUntilStopped();
+ t1Radius.text = 'radius: ' + t1.shader.props.radius!.toString();
+
+ await snapshot({ name: 'animation1' });
+
+ const shaderAnimation2 = t2.animate(
+ {
+ x: 1140,
+ shaderProps: {
+ r1: {
+ radius: 150,
+ },
+ e1: {
+ width: 50,
+ },
+ },
+ },
+ {
+ duration: 500,
+ },
+ );
+
+ shaderAnimation2.start();
+ await shaderAnimation2.waitUntilStopped();
+ t2Radius.text = 'radius: ' + t2.shader.props.r1.radius!.toString();
+ t2Border.text = 'border: ' + t2.shader.props.e1.width!.toString();
+
+ await snapshot({ name: 'animation2' });
+ console.log('ready!');
+}
diff --git a/examples/tests/stress-multi-level-clipping.ts b/examples/tests/stress-multi-level-clipping.ts
index 42085cc0..41becb0c 100644
--- a/examples/tests/stress-multi-level-clipping.ts
+++ b/examples/tests/stress-multi-level-clipping.ts
@@ -18,7 +18,6 @@
*/
import { type INode } from '@lightningjs/renderer';
-import logo from '../assets/lightning.png';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import robotImg from '../assets/robot/robot.png';
diff --git a/examples/tests/stress-single-level-text.ts b/examples/tests/stress-single-level-text.ts
index a299dc4d..cf5bdd35 100644
--- a/examples/tests/stress-single-level-text.ts
+++ b/examples/tests/stress-single-level-text.ts
@@ -18,7 +18,6 @@
*/
import { type INode } from '@lightningjs/renderer';
-import logo from '../assets/lightning.png';
import type { ExampleSettings } from '../common/ExampleSettings.js';
const randomIntBetween = (from: number, to: number) =>
diff --git a/examples/tests/stress-single-level.ts b/examples/tests/stress-single-level.ts
index 56fd968c..f488dfed 100644
--- a/examples/tests/stress-single-level.ts
+++ b/examples/tests/stress-single-level.ts
@@ -30,7 +30,7 @@ export default async function ({
perfMultiplier,
}: ExampleSettings) {
// create 100 nodes
- const numOuterNodes = 100 * perfMultiplier;
+ const numOuterNodes = 1 * perfMultiplier;
const nodes: INode[] = [];
const bg = renderer.createNode({
@@ -46,10 +46,12 @@ export default async function ({
height: 101,
x: Math.random() * 1920,
y: Math.random() * 1080,
- src: logo,
+ // src: logo,
parent: bg,
});
+ node.src = logo;
+
nodes.push(node);
}
diff --git a/examples/tests/test.ts b/examples/tests/test.ts
index 15844363..28a51058 100644
--- a/examples/tests/test.ts
+++ b/examples/tests/test.ts
@@ -169,17 +169,12 @@ export default async function ({ renderer, testRoot }: ExampleSettings) {
});
setInterval(() => {
- shaft.texture = renderer.createTexture(
- 'NoiseTexture',
- {
- width: 210,
- height: renderer.settings.appHeight,
- cacheId: Math.floor(Math.random() * 100000),
- },
- {
- preload: true,
- },
- );
+ shaft.texture = renderer.createTexture('NoiseTexture', {
+ width: 210,
+ height: renderer.settings.appHeight,
+ cacheId: Math.floor(Math.random() * 100000),
+ });
+ shaft.textureOptions.preload = true;
}, 1000);
// setTimeout required for ThreadX right now because the emit() that sends
diff --git a/examples/tests/text-alpha.ts b/examples/tests/text-alpha.ts
index 4347e72e..7f4e0eb1 100644
--- a/examples/tests/text-alpha.ts
+++ b/examples/tests/text-alpha.ts
@@ -17,14 +17,14 @@
* limitations under the License.
*/
+import type {
+ INodeProps,
+ ITextNodeProps,
+ RendererMain,
+} from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
-import type {
- INodeWritableProps,
- ITextNodeWritableProps,
- RendererMain,
-} from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
const containerSize = 100;
@@ -38,7 +38,7 @@ const NODE_PROPS = {
fontFamily: 'Ubuntu',
textRendererOverride: 'sdf',
fontSize: 50,
-} satisfies Partial;
+} satisfies Partial;
export async function automation(settings: ExampleSettings) {
// Snapshot all the pages
@@ -73,7 +73,7 @@ function generateAlphaTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode, containerSize }, [
renderer.createTextNode({
@@ -103,7 +103,7 @@ function generateAlphaTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode, containerSize }, [
createContainedTextNode(renderer, textRenderer, {
@@ -130,7 +130,7 @@ function generateAlphaTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode, containerSize }, [
renderer.createTextNode({
@@ -159,7 +159,7 @@ function generateAlphaTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode, containerSize }, [
createContainedTextNode(renderer, textRenderer, {
@@ -188,7 +188,7 @@ function generateAlphaTest(
function createContainedTextNode(
renderer: RendererMain,
textRenderer: 'canvas' | 'sdf',
- containerProps: Partial,
+ containerProps: Partial,
) {
const container = renderer.createNode({
width: containerSize,
diff --git a/examples/tests/text-baseline.ts b/examples/tests/text-baseline.ts
index ba752705..529e9b0a 100644
--- a/examples/tests/text-baseline.ts
+++ b/examples/tests/text-baseline.ts
@@ -17,14 +17,11 @@
* limitations under the License.
*/
+import type { ITextNodeProps, RendererMain } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
import { waitForLoadedDimensions } from '../common/utils.js';
-import type {
- ITextNodeWritableProps,
- RendererMain,
-} from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
export async function automation(settings: ExampleSettings) {
@@ -57,7 +54,7 @@ const NODE_PROPS = {
textRendererOverride: 'sdf',
fontSize: 50,
lineHeight: 70,
-} satisfies Partial;
+} satisfies Partial;
function generateBaselineTest(
renderer: RendererMain,
@@ -72,10 +69,11 @@ function generateBaselineTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
+ parent: renderer.root,
});
const dimensions = await waitForLoadedDimensions(baselineNode);
diff --git a/examples/tests/text-canvas.ts b/examples/tests/text-canvas.ts
new file mode 100644
index 00000000..d3cee531
--- /dev/null
+++ b/examples/tests/text-canvas.ts
@@ -0,0 +1,156 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2024 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { ExampleSettings } from '../common/ExampleSettings.js';
+
+const Colors = {
+ Black: 0x000000ff,
+ Red: 0xff0000ff,
+ Green: 0x00ff00ff,
+ Blue: 0x0000ffff,
+ Magenta: 0xff00ffff,
+ Gray: 0x7f7f7fff,
+ White: 0xffffffff,
+};
+
+const randomIntBetween = (from: number, to: number) =>
+ Math.floor(Math.random() * (to - from + 1) + from);
+
+/**
+ * Tests that Single-Channel Signed Distance Field (SSDF) fonts are rendered
+ * correctly.
+ *
+ * Text that is thinner than the certified snapshot may indicate that the
+ * SSDF font atlas texture was premultiplied before being uploaded to the GPU.
+ *
+ * @param settings
+ * @returns
+ */
+export default async function test(settings: ExampleSettings) {
+ const { renderer, testRoot } = settings;
+
+ // Set a smaller snapshot area
+ // testRoot.width = 200;
+ // testRoot.height = 200;
+ // testRoot.color = 0xffffffff;
+
+ const nodes: any[] = [];
+
+ const renderNode = (t: string) => {
+ const node = renderer.createTextNode({
+ x: Math.random() * 1900,
+ y: Math.random() * 1080,
+ text: 'CANVAS ' + t,
+ fontFamily: 'sans-serif',
+ parent: testRoot,
+ fontSize: 80,
+ });
+
+ nodes.push(node);
+
+ // pick random color from Colors
+ node.color =
+ Object.values(Colors)[
+ randomIntBetween(0, Object.keys(Colors).length - 1)
+ ] || 0xff0000ff;
+ };
+
+ const spawn = (amount = 100) => {
+ for (let i = 0; i < amount; i++) {
+ renderNode(i.toString());
+ }
+ };
+
+ const despawn = (amount = 100) => {
+ for (let i = 0; i < amount; i++) {
+ const node = nodes.pop();
+ node.destroy();
+ }
+ };
+
+ const move = () => {
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ node.x = randomIntBetween(0, 1600);
+ node.y = randomIntBetween(0, 880);
+ }
+ };
+
+ const newColor = () => {
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ node.color =
+ Object.values(Colors)[
+ randomIntBetween(0, Object.keys(Colors).length - 1)
+ ] || 0x000000ff;
+ }
+ };
+
+ let animating = false;
+ const animate = () => {
+ animating = !animating;
+
+ const animateNode = (node: any) => {
+ nodes.forEach((node) => {
+ node
+ .animate(
+ {
+ x: randomIntBetween(20, 1740),
+ y: randomIntBetween(20, 900),
+ rotation: Math.random() * Math.PI,
+ },
+ {
+ duration: 3000,
+ easing: 'ease-out',
+ },
+ )
+ .start();
+ });
+ };
+
+ const animateRun = () => {
+ if (animating) {
+ for (let i = 0; i < nodes.length; i++) {
+ animateNode(nodes[i]);
+ }
+ setTimeout(animateRun, 3050);
+ }
+ };
+
+ animateRun();
+ };
+
+ window.addEventListener('keydown', (event) => {
+ if (event.key === 'ArrowUp') {
+ spawn();
+ } else if (event.key === 'ArrowDown') {
+ despawn();
+ } else if (event.key === 'ArrowLeft') {
+ move();
+ } else if (event.key === 'ArrowRight') {
+ move();
+ } else if (event.key === '1') {
+ newColor();
+ } else if (event.key === ' ') {
+ animate();
+ }
+ });
+
+ spawn();
+}
diff --git a/examples/tests/text-events.ts b/examples/tests/text-events.ts
index 9532ae1b..884aa03f 100644
--- a/examples/tests/text-events.ts
+++ b/examples/tests/text-events.ts
@@ -33,13 +33,9 @@ const FONT_SIZE = 60;
const BUTTON_PADDING = 10;
const BEGIN_Y = HEADER_SIZE;
-export default async function ({
- renderer,
- driverName,
- testRoot,
-}: ExampleSettings) {
+export default async function ({ renderer, testRoot }: ExampleSettings) {
const header = renderer.createTextNode({
- text: `Text Event Test (${driverName})`,
+ text: `Text Event Test`,
fontSize: HEADER_SIZE,
offsetY: -5,
parent: testRoot,
diff --git a/examples/tests/text-line-height.ts b/examples/tests/text-line-height.ts
index c2aad222..12f41035 100644
--- a/examples/tests/text-line-height.ts
+++ b/examples/tests/text-line-height.ts
@@ -17,14 +17,10 @@
* limitations under the License.
*/
+import type { ITextNodeProps, RendererMain } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
-import { waitForLoadedDimensions } from '../common/utils.js';
-import type {
- ITextNodeWritableProps,
- RendererMain,
-} from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
export async function automation(settings: ExampleSettings) {
@@ -57,7 +53,7 @@ const NODE_PROPS = {
fontFamily: 'Ubuntu',
textRendererOverride: 'sdf',
fontSize: 50,
-} satisfies Partial;
+} satisfies Partial;
function generateLineHeightTest(
renderer: RendererMain,
@@ -72,7 +68,7 @@ function generateLineHeightTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
diff --git a/examples/tests/text-max-lines.ts b/examples/tests/text-max-lines.ts
index 4f579134..5c1a161f 100644
--- a/examples/tests/text-max-lines.ts
+++ b/examples/tests/text-max-lines.ts
@@ -17,13 +17,10 @@
* limitations under the License.
*/
+import type { ITextNodeProps, RendererMain } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
-import type {
- ITextNodeWritableProps,
- RendererMain,
-} from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
import { getLoremIpsum } from '../common/LoremIpsum.js';
@@ -59,7 +56,7 @@ const BASE_NODE_PROPS = {
fontSize: 20,
lineHeight: 28,
contain: 'width',
-} satisfies Partial;
+} satisfies Partial;
function generateMaxLinesTest(
renderer: RendererMain,
@@ -73,7 +70,7 @@ function generateMaxLinesTest(
...BASE_NODE_PROPS,
text: 'Line1 Line1_Line1_Line1\nLine2 Line2____Line2\nLine 3\nLine 4',
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
@@ -129,7 +126,7 @@ function generateMaxLinesTest(
...BASE_NODE_PROPS,
text: getLoremIpsum(100),
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
diff --git a/examples/tests/text-offscreen-move.ts b/examples/tests/text-offscreen-move.ts
index dd0eaa09..51039889 100644
--- a/examples/tests/text-offscreen-move.ts
+++ b/examples/tests/text-offscreen-move.ts
@@ -19,7 +19,7 @@
import type {
INode,
- ITextNodeWritableProps,
+ ITextNodeProps,
RendererMain,
} from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
@@ -68,12 +68,12 @@ const commonTextProps = {
fontFamily: 'Ubuntu',
textRendererOverride: 'canvas',
fontSize: 50,
-} satisfies Partial;
+} satisfies Partial;
function createTestCase(
renderer: RendererMain,
textRenderer: 'canvas' | 'sdf',
- contain: ITextNodeWritableProps['contain'],
+ contain: ITextNodeProps['contain'],
) {
return async function (page: INode) {
const subheader = renderer.createTextNode({
diff --git a/examples/tests/text-overflow-suffix.ts b/examples/tests/text-overflow-suffix.ts
index 415179b4..2cdbbd4e 100644
--- a/examples/tests/text-overflow-suffix.ts
+++ b/examples/tests/text-overflow-suffix.ts
@@ -17,13 +17,10 @@
* limitations under the License.
*/
+import type { ITextNodeProps, RendererMain } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
-import type {
- ITextNodeWritableProps,
- RendererMain,
-} from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
import { getLoremIpsum } from '../common/LoremIpsum.js';
@@ -60,7 +57,7 @@ const NODE_PROPS = {
fontSize: 20,
lineHeight: 28,
contain: 'both',
-} satisfies Partial;
+} satisfies Partial;
function generateOverflowSuffixTest(
renderer: RendererMain,
@@ -73,7 +70,7 @@ function generateOverflowSuffixTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
diff --git a/examples/tests/text-rotation.ts b/examples/tests/text-rotation.ts
index 8422069f..460eea34 100644
--- a/examples/tests/text-rotation.ts
+++ b/examples/tests/text-rotation.ts
@@ -17,14 +17,11 @@
* limitations under the License.
*/
+import type { ITextNodeProps, RendererMain } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
import { waitForLoadedDimensions } from '../common/utils.js';
-import type {
- ITextNodeWritableProps,
- RendererMain,
-} from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
export async function automation(settings: ExampleSettings) {
@@ -56,7 +53,7 @@ const NODE_PROPS = {
fontFamily: 'Ubuntu',
textRendererOverride: 'sdf',
fontSize: 50,
-} satisfies Partial;
+} satisfies Partial;
function generateRotationTest(
renderer: RendererMain,
@@ -69,7 +66,7 @@ function generateRotationTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
@@ -120,7 +117,7 @@ function generateRotationTest(
x: 100,
y: 100,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
return await constructTestRow({ renderer, rowNode }, [
renderer.createTextNode({
@@ -154,7 +151,7 @@ function generateRotationTest(
...NODE_PROPS,
mount: 1,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
diff --git a/examples/tests/text-scaling.ts b/examples/tests/text-scaling.ts
index 0314e230..aac310fb 100644
--- a/examples/tests/text-scaling.ts
+++ b/examples/tests/text-scaling.ts
@@ -17,14 +17,11 @@
* limitations under the License.
*/
+import type { ITextNodeProps, RendererMain } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
import { PageContainer } from '../common/PageContainer.js';
import { waitForLoadedDimensions } from '../common/utils.js';
-import type {
- ITextNodeWritableProps,
- RendererMain,
-} from '../../dist/exports/main-api.js';
import { constructTestRow } from '../common/constructTestRow.js';
export async function automation(settings: ExampleSettings) {
@@ -61,7 +58,7 @@ const NODE_PROPS = {
fontFamily: 'Ubuntu',
textRendererOverride: 'sdf',
fontSize: 50,
-} satisfies Partial;
+} satisfies Partial;
function generateScalingTest(
renderer: RendererMain,
@@ -75,7 +72,7 @@ function generateScalingTest(
const nodeProps = {
...NODE_PROPS,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
@@ -145,7 +142,7 @@ function generateScalingTest(
x: 100,
y: 100,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
@@ -200,7 +197,7 @@ function generateScalingTest(
...NODE_PROPS,
mount: 1,
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
diff --git a/examples/tests/text-vertical-align.ts b/examples/tests/text-vertical-align.ts
index 13face40..4b8337f6 100644
--- a/examples/tests/text-vertical-align.ts
+++ b/examples/tests/text-vertical-align.ts
@@ -17,14 +17,14 @@
* limitations under the License.
*/
-import type { ExampleSettings } from '../common/ExampleSettings.js';
-import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
-import { PageContainer } from '../common/PageContainer.js';
import type {
ITextNode,
- ITextNodeWritableProps,
+ ITextNodeProps,
RendererMain,
-} from '../../dist/exports/main-api.js';
+} from '@lightningjs/renderer';
+import type { ExampleSettings } from '../common/ExampleSettings.js';
+import { paginateTestRows, type TestRow } from '../common/paginateTestRows.js';
+import { PageContainer } from '../common/PageContainer.js';
import { constructTestRow } from '../common/constructTestRow.js';
export async function automation(settings: ExampleSettings) {
@@ -55,7 +55,7 @@ const NODE_PROPS = {
textRendererOverride: 'sdf',
fontSize: 50,
lineHeight: 70,
-} satisfies Partial;
+} satisfies Partial;
const CONTAINER_SIZE = 200;
@@ -94,7 +94,7 @@ function generateVerticalAlignTest(
...NODE_PROPS,
text: 'txyz',
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
@@ -129,7 +129,7 @@ function generateVerticalAlignTest(
...NODE_PROPS,
text: 'abcd\ntxyz',
textRendererOverride: textRenderer,
- } satisfies Partial;
+ } satisfies Partial;
const baselineNode = renderer.createTextNode({
...nodeProps,
diff --git a/examples/tests/text.ts b/examples/tests/text.ts
index 197d3a97..174fe588 100644
--- a/examples/tests/text.ts
+++ b/examples/tests/text.ts
@@ -18,7 +18,7 @@
*/
import {
- type ITextNodeWritableProps,
+ type ITextNodeProps,
type TextRendererMap,
type TrFontFaceMap,
type NodeLoadedEventHandler,
@@ -35,7 +35,7 @@ const FONT_FAMILY = 'Ubuntu';
const HEADER_SIZE = 45;
const FONT_SIZE = 40;
-const initialMutableProps: Partial = {
+const initialMutableProps: Partial = {
x: 0,
y: 0,
fontFamily: FONT_FAMILY,
@@ -57,7 +57,7 @@ export const Colors = {
};
interface LocalStorageData {
- mutableProps: Partial;
+ mutableProps: Partial;
curMode: number;
moveStep: number;
curColorIdx: number;
@@ -87,7 +87,7 @@ export default async function ({
const text = getLoremIpsum();
- const initialProps: Partial = {
+ const initialProps: Partial = {
...(savedState?.mutableProps || initialMutableProps),
fontFamily: FONT_FAMILY,
contain: 'both',
diff --git a/examples/tests/reference-texture-memory.ts b/examples/tests/texture-cleanup-critical.ts
similarity index 60%
rename from examples/tests/reference-texture-memory.ts
rename to examples/tests/texture-cleanup-critical.ts
index 89b16ff0..f04d0d6b 100644
--- a/examples/tests/reference-texture-memory.ts
+++ b/examples/tests/texture-cleanup-critical.ts
@@ -16,26 +16,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import type { RendererMainSettings } from '../../dist/exports/main-api.js';
+import type { RendererMainSettings } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
-export function customSettings(
- urlParams: URLSearchParams,
-): Partial {
- const finalizationRegistry = urlParams.get('finalizationRegistry') === 'true';
+export function customSettings(): Partial {
return {
- textureCleanupOptions: {
- textureCleanupAgeThreadholdMs: 6000,
- textureCleanupIntervalMs: 1000,
+ textureMemory: {
+ criticalThreshold: 100 * 1024 ** 2,
+ targetThresholdLevel: 0.25,
+ debugLogging: true,
},
- // Disable the threshold-based memory manager. This will allow this test to
- // focus only on the reference-based memory manager.
- txMemByteThreshold: 0,
- experimental_FinalizationRegistryTextureUsageTracker: finalizationRegistry,
};
}
-export default async function ({ renderer, testRoot }: ExampleSettings) {
+export default async function ({
+ renderer,
+ testRoot,
+ memMonitor,
+}: ExampleSettings) {
+ // Make the memory monitor update fast
+ if (memMonitor) {
+ memMonitor.interval = 10;
+ }
const screen = renderer.createNode({
x: 0,
y: 0,
@@ -48,7 +50,7 @@ export default async function ({ renderer, testRoot }: ExampleSettings) {
renderer.createTextNode({
x: 0,
y: 0,
- text: 'Reference-based Texture Memory Management Test',
+ text: 'Critical Texture Memory Cleanup Test',
parent: screen,
fontFamily: 'Ubuntu',
fontSize: 60,
@@ -59,7 +61,7 @@ export default async function ({ renderer, testRoot }: ExampleSettings) {
y: 100,
width: renderer.settings.appWidth,
contain: 'width',
- text: `This test will create and display a random NoiseTexture node every 10ms.
+ text: `This test will create and display a random NoiseTexture node every 10ms and never offer a moment for Idle Texture Cleanup. Only Critical Texture Cleanup will be triggered.
See docs/ManualRegressionTests.md for more information.
`,
@@ -70,16 +72,11 @@ See docs/ManualRegressionTests.md for more information.
// Create a new random texture every 10ms
setInterval(() => {
- screen.texture = renderer.createTexture(
- 'NoiseTexture',
- {
- width: 500,
- height: 500,
- cacheId: Math.floor(Math.random() * 100000),
- },
- {
- preload: true,
- },
- );
+ screen.texture = renderer.createTexture('NoiseTexture', {
+ width: 500,
+ height: 500,
+ cacheId: Math.floor(Math.random() * 100000),
+ });
+ screen.textureOptions.preload = true;
}, 10);
}
diff --git a/examples/tests/threshold-texture-memory.ts b/examples/tests/texture-cleanup-idle.ts
similarity index 74%
rename from examples/tests/threshold-texture-memory.ts
rename to examples/tests/texture-cleanup-idle.ts
index ddb5c0da..8fd0efe6 100644
--- a/examples/tests/threshold-texture-memory.ts
+++ b/examples/tests/texture-cleanup-idle.ts
@@ -16,23 +16,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import type { INode, RendererMainSettings } from '@lightningjs/renderer';
import type { ExampleSettings } from '../common/ExampleSettings.js';
-export function customSettings(
- urlParams: URLSearchParams,
-): Partial {
- const finalizationRegistry = urlParams.get('finalizationRegistry') === 'true';
- const txMemByteThreshold = urlParams.get('txMemByteThreshold');
+export function customSettings(): Partial {
return {
- textureCleanupOptions: {
- textureCleanupAgeThreadholdMs: 6000,
- textureCleanupIntervalMs: 1000,
+ textureMemory: {
+ cleanupInterval: 5000,
+ debugLogging: true,
},
- txMemByteThreshold: txMemByteThreshold
- ? Number(txMemByteThreshold)
- : 100000000 /* 100MB */,
- experimental_FinalizationRegistryTextureUsageTracker: finalizationRegistry,
};
}
@@ -61,7 +54,7 @@ export default async function ({ renderer, testRoot }: ExampleSettings) {
renderer.createTextNode({
x: 0,
y: 0,
- text: 'Threshold-based Texture Memory Management Test',
+ text: 'Idle Texture Memory Cleanup Test',
parent: testRoot,
fontFamily: 'Ubuntu',
fontSize: 60,
@@ -73,7 +66,9 @@ export default async function ({ renderer, testRoot }: ExampleSettings) {
y: 100,
width: renderer.settings.appWidth,
contain: 'width',
- text: `This test will create and display a grid of random NoiseTexture nodes and move them off of the bounds margin every 100ms.
+ text: `This test will create and display a grid of random NoiseTexture nodes and move them off of the bounds margin every second.
+
+The Texture Memory Manager should perform Idle Texture Cleanup roughly every 5 seconds.
See docs/ManualRegressionTests.md for more information.
`,
@@ -103,22 +98,19 @@ See docs/ManualRegressionTests.md for more information.
height: nodeHeight,
parent: testRoot,
color: randomColor(),
- texture: renderer.createTexture(
- 'NoiseTexture',
- {
- width: nodeWidth,
- height: nodeHeight,
- cacheId: Math.floor(Math.random() * 100000),
- },
- {
- preload: true,
- },
- ),
+ texture: renderer.createTexture('NoiseTexture', {
+ width: nodeWidth,
+ height: nodeHeight,
+ cacheId: Math.floor(Math.random() * 100000),
+ }),
+ textureOptions: {
+ preload: true,
+ },
});
curNodes.push(node);
}
}
- await delay(100);
+ await delay(1000);
// Move all nodes offscreen beyond the bounds margin
for (const node of curNodes) {
node.x = -screenWidth * 2;
diff --git a/examples/tests/texture-factory.ts b/examples/tests/texture-factory.ts
index f621a38f..14e90b7d 100644
--- a/examples/tests/texture-factory.ts
+++ b/examples/tests/texture-factory.ts
@@ -25,11 +25,7 @@ export async function automation(settings: ExampleSettings) {
await settings.snapshot();
}
-export default async function test({
- renderer,
- driverName,
- testRoot,
-}: ExampleSettings) {
+export default async function test({ renderer, testRoot }: ExampleSettings) {
const randomColor = () => {
const randomInt = Math.floor(Math.random() * Math.pow(2, 32));
const hexString = randomInt.toString(16).padStart(8, '0');
@@ -43,7 +39,7 @@ export default async function test({
const FONT_SIZE = 45;
renderer.createTextNode({
- text: `Texture Factory Test (${driverName})`,
+ text: `Texture Factory Test`,
fontSize: FONT_SIZE,
offsetY: -5,
parent: testRoot,
diff --git a/examples/tests/textures.ts b/examples/tests/textures.ts
index d72aab8f..60009545 100644
--- a/examples/tests/textures.ts
+++ b/examples/tests/textures.ts
@@ -33,17 +33,13 @@ export async function automation(settings: ExampleSettings) {
await settings.snapshot();
}
-export default async function test({
- renderer,
- driverName,
- testRoot,
-}: ExampleSettings) {
+export default async function test({ renderer, testRoot }: ExampleSettings) {
const FONT_SIZE = 45;
const BEGIN_Y = FONT_SIZE;
const header = renderer.createTextNode({
fontFamily: 'Ubuntu',
- text: `Texture Test (${driverName})`,
+ text: `Texture Test`,
fontSize: FONT_SIZE,
parent: testRoot,
});
diff --git a/examples/tests/viewport-events-canvas.ts b/examples/tests/viewport-events-canvas.ts
new file mode 100644
index 00000000..e9b6858b
--- /dev/null
+++ b/examples/tests/viewport-events-canvas.ts
@@ -0,0 +1,208 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2024 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { ExampleSettings } from '../common/ExampleSettings.js';
+
+export default async function ({ renderer, testRoot }: ExampleSettings) {
+ const instructionText = renderer.createTextNode({
+ text: 'Press space to start animation, arrow keys to move, enter to reset',
+ fontSize: 30,
+ x: 10,
+ y: 960,
+ fontFamily: 'Ubuntu-ssdf',
+ parent: testRoot,
+ });
+
+ const redStatus = renderer.createTextNode({
+ text: 'Red Status: ',
+ fontSize: 30,
+ x: 10,
+ y: 50,
+ fontFamily: 'Ubuntu-ssdf',
+ parent: testRoot,
+ });
+
+ const blueStatus = renderer.createTextNode({
+ text: 'Blue Status: ',
+ fontSize: 30,
+ x: 10,
+ y: 10,
+ fontFamily: 'Ubuntu-ssdf',
+ parent: testRoot,
+ });
+
+ const boundaryRect = renderer.createNode({
+ x: 1920 / 2 - (1920 * 0.75) / 2,
+ y: 1080 / 2 - (1080 * 0.75) / 2,
+ width: 1440,
+ height: 810,
+ color: 0x000000ff,
+ clipping: true,
+ parent: testRoot,
+ });
+
+ const redText = renderer.createTextNode({
+ x: 500,
+ y: 305,
+ alpha: 1,
+ width: 200,
+ height: 200,
+ color: 0xff0000ff,
+ pivot: 0,
+ text: 'red',
+ fontSize: 80,
+ fontFamily: 'sans-serif',
+ parent: boundaryRect,
+ });
+
+ redText.on('outOfBounds', () => {
+ console.log('red text out of bounds');
+ redStatus.text = 'Red Status: text out of bounds';
+ redStatus.color = 0xff0000ff;
+ });
+
+ redText.on('inViewport', () => {
+ console.log('red text in view port');
+ redStatus.text = 'Red Status: text in view port';
+ redStatus.color = 0x00ff00ff;
+ });
+
+ redText.on('inBounds', () => {
+ console.log('red text inside render bounds');
+ redStatus.text = 'Red Status: text in bounds';
+ redStatus.color = 0xffff00ff;
+ });
+
+ const blueText = renderer.createTextNode({
+ x: 1920 / 2 - 200,
+ y: 100,
+ alpha: 1,
+ width: 200,
+ height: 200,
+ color: 0x0000ffff,
+ pivot: 0,
+ text: 'blue',
+ fontSize: 80,
+ fontFamily: 'sans-serif',
+ parent: testRoot,
+ });
+
+ blueText.on('outOfBounds', () => {
+ console.log('blue text ouf ot bounds');
+ blueStatus.text = 'Blue Status: blue text out of bounds';
+ blueStatus.color = 0xff0000ff;
+ });
+
+ blueText.on('inViewport', () => {
+ console.log('blue text in view port');
+ blueStatus.text = 'Blue Status: blue text in view port';
+ blueStatus.color = 0x00ff00ff;
+ });
+
+ blueText.on('inBounds', () => {
+ console.log('blue text inside render bounds');
+ blueStatus.text = 'Blue Status: blue text in bounds';
+ blueStatus.color = 0xffff00ff;
+ });
+
+ let runAnimation = false;
+ const animate = async () => {
+ redText
+ .animate(
+ {
+ x: -500,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start();
+
+ await blueText
+ .animate(
+ {
+ x: -1200,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start()
+ .waitUntilStopped();
+
+ redText.x = 1920 + 400;
+ blueText.x = 1920 + 400;
+
+ redText
+ .animate(
+ {
+ x: 520,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start();
+
+ await blueText
+ .animate(
+ {
+ x: 1920 / 2 - 200,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start()
+ .waitUntilStopped();
+
+ if (runAnimation) {
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ setTimeout(animate, 2000);
+ }
+ };
+
+ const moveModifier = 10;
+ window.onkeydown = (e) => {
+ if (e.key === ' ') {
+ runAnimation = !runAnimation;
+
+ if (runAnimation) {
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
+ animate();
+ }
+ }
+
+ if (e.key === 'ArrowRight') {
+ redText.x += moveModifier;
+ blueText.x += moveModifier;
+ }
+
+ if (e.key === 'ArrowLeft') {
+ redText.x -= moveModifier;
+ blueText.x -= moveModifier;
+ }
+
+ if (e.key === 'Enter') {
+ runAnimation = false;
+ redText.x = 520;
+ blueText.x = 1920 / 2 - 200;
+ }
+ };
+}
diff --git a/examples/tests/viewport-events.ts b/examples/tests/viewport-events.ts
new file mode 100644
index 00000000..19da04a7
--- /dev/null
+++ b/examples/tests/viewport-events.ts
@@ -0,0 +1,185 @@
+import type { ExampleSettings } from '../common/ExampleSettings.js';
+
+export default async function ({ renderer, testRoot }: ExampleSettings) {
+ const degToRad = (deg: number) => {
+ return (Math.PI / 180) * deg;
+ };
+
+ const instructionText = renderer.createTextNode({
+ text: 'Press space to start animation, arrow keys to move, enter to reset',
+ fontSize: 30,
+ x: 10,
+ y: 960,
+ parent: testRoot,
+ });
+
+ const redStatus = renderer.createTextNode({
+ text: 'Red Status: ',
+ fontSize: 30,
+ x: 10,
+ y: 50,
+ parent: testRoot,
+ });
+
+ const blueStatus = renderer.createTextNode({
+ text: 'Blue Status: ',
+ fontSize: 30,
+ x: 10,
+ y: 10,
+ parent: testRoot,
+ });
+
+ const boundaryRect = renderer.createNode({
+ x: 1920 / 2 - (1920 * 0.75) / 2,
+ y: 1080 / 2 - (1080 * 0.75) / 2,
+ width: 1440,
+ height: 810,
+ color: 0x000000ff,
+ clipping: true,
+ parent: testRoot,
+ });
+
+ const redRect = renderer.createNode({
+ // skipRender: true,
+ x: 520,
+ y: 305,
+ alpha: 1,
+ width: 200,
+ height: 200,
+ color: 0xff0000ff,
+ pivot: 0,
+ parent: boundaryRect,
+ });
+
+ redRect.on('outOfBounds', () => {
+ console.log('red rect out of bounds');
+ redStatus.text = 'Red Status: rect out of bounds';
+ redStatus.color = 0xff0000ff;
+ });
+
+ redRect.on('inViewport', () => {
+ console.log('red rect in view port');
+ redStatus.text = 'Red Status: rect in view port';
+ redStatus.color = 0x00ff00ff;
+ });
+
+ redRect.on('inBounds', () => {
+ console.log('red rect inside render bounds');
+ redStatus.text = 'Red Status: rect in bounds';
+ redStatus.color = 0xffff00ff;
+ });
+
+ const blueRect = renderer.createNode({
+ x: 1920 / 2 - 200,
+ y: 100,
+ alpha: 1,
+ width: 200,
+ height: 200,
+ color: 0x0000ffff,
+ pivot: 0,
+ parent: testRoot,
+ });
+
+ blueRect.on('outOfBounds', () => {
+ console.log('blue rect ouf ot bounds');
+ blueStatus.text = 'Blue Status: blue rect out of bounds';
+ blueStatus.color = 0xff0000ff;
+ });
+
+ blueRect.on('inViewport', () => {
+ console.log('blue rect in view port');
+ blueStatus.text = 'Blue Status: blue rect in view port';
+ blueStatus.color = 0x00ff00ff;
+ });
+
+ blueRect.on('inBounds', () => {
+ console.log('blue rect inside render bounds');
+ blueStatus.text = 'Blue Status: blue rect in bounds';
+ blueStatus.color = 0xffff00ff;
+ });
+
+ let runAnimation = false;
+ const animate = async () => {
+ redRect
+ .animate(
+ {
+ x: -500,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start();
+
+ await blueRect
+ .animate(
+ {
+ x: -1200,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start()
+ .waitUntilStopped();
+
+ redRect.x = 1920 + 400;
+ blueRect.x = 1920 + 400;
+
+ redRect
+ .animate(
+ {
+ x: 520,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start();
+
+ await blueRect
+ .animate(
+ {
+ x: 1920 / 2 - 200,
+ },
+ {
+ duration: 4000,
+ },
+ )
+ .start()
+ .waitUntilStopped();
+
+ if (runAnimation) {
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ setTimeout(animate, 2000);
+ }
+ };
+
+ const moveModifier = 10;
+ window.onkeydown = (e) => {
+ if (e.key === ' ') {
+ runAnimation = !runAnimation;
+
+ if (runAnimation) {
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
+ animate();
+ }
+ }
+
+ if (e.key === 'ArrowRight') {
+ redRect.x += moveModifier;
+ blueRect.x += moveModifier;
+ }
+
+ if (e.key === 'ArrowLeft') {
+ redRect.x -= moveModifier;
+ blueRect.x -= moveModifier;
+ }
+
+ if (e.key === 'Enter') {
+ runAnimation = false;
+ redRect.x = 520;
+ blueRect.x = 1920 / 2 - 200;
+ }
+ };
+}
diff --git a/examples/vite-env.d.ts b/examples/vite-env.d.ts
index 72d7a860..77dd71a8 100644
--- a/examples/vite-env.d.ts
+++ b/examples/vite-env.d.ts
@@ -19,5 +19,3 @@
///
// This enables Vite's import.meta augmentations and possibly other things?
-///
-// This installs 'import' types from the 'vite-plugin-import-chunk-url' plugin
diff --git a/examples/vite.config.ts b/examples/vite.config.ts
index 7b4888d3..b9698741 100644
--- a/examples/vite.config.ts
+++ b/examples/vite.config.ts
@@ -19,7 +19,6 @@
import { defineConfig } from 'vite';
import * as path from 'path';
-import { importChunkUrl } from '@lightningjs/vite-plugin-import-chunk-url';
/**
* Targeting ES2019 gets us at least to WPE 2.28
@@ -47,9 +46,9 @@ const devTarget = 'es2020';
/**
* Vite Config
*/
-export default defineConfig(({ command, mode, ssrBuild }) => {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export default defineConfig(({ command, mode, isSsrBuild }) => {
return {
- plugins: [importChunkUrl()],
worker: {
format: 'es',
},
diff --git a/exports/core-api.ts b/exports/core-api.ts
deleted file mode 100644
index 34e7bca1..00000000
--- a/exports/core-api.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * If not stated otherwise in this file or this component's LICENSE file the
- * following copyright and licenses apply:
- *
- * Copyright 2023 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- * Lightning 3 Renderer Core API
- *
- * @remarks
- * ```
- * import * from '@lightning/renderer/core';
- * ```
- *
- * The Core API is used by developers to extend the capabilities of the Renderer
- * by writing custom Shaders, Dynamic Shader Effects, Textures, Text Renderers,
- * etc.
- *
- * Custom capabilities as well as fonts can be loaded via Core Extensions.
- *
- * A core extension module is structured like so:
- * ```ts
- * import {
- * CoreExtension,
- * WebTrFontFace,
- * SdfTrFontFace,
- * type Stage
- * } from '@lightning/renderer/core';
- *
- * export default class MyCoreExtension extends CoreExtension {
- * async run(stage: Stage) {
- * stage.fontManager.addFontFace(
- * new WebTrFontFace('Ubuntu', {}, '/fonts/Ubuntu-Regular.ttf'),
- * );
- *
- * stage.fontManager.addFontFace(
- * new SdfTrFontFace(
- * 'Ubuntu',
- * {},
- * 'msdf',
- * stage,
- * '/fonts/Ubuntu-Regular.msdf.png',
- * '/fonts/Ubuntu-Regular.msdf.json',
- * ),
- * );
- * }
- * }
- * ```
- *
- * And then imported and registered in the application's entry point
- * using the `@lightningjs/vite-plugin-import-chunk-url` plugin:
- * ```ts
- * import coreExtensionModuleUrl from './MyCoreExtension.js?importChunkUrl';
- *
- * // Set up driver, etc.
- *
- * // Initialize the Renderer
- * const renderer = new RendererMain(
- * {
- * // Other Renderer Config...
- * coreExtensionModule: coreExtensionModuleUrl,
- * },
- * 'app',
- * driver,
- * );
- * ```
- *
- * @module
- */
-
-// Shaders
-export * from '../src/core/renderers/webgl/WebGlCoreShader.js';
-export * from '../src/core/renderers/webgl/shaders/effects/ShaderEffect.js';
-
-// Textures
-export * from '../src/core/textures/Texture.js';
-
-// Text Rendering & Fonts
-export * from '../src/core/text-rendering/renderers/TextRenderer.js';
-export * from '../src/core/text-rendering/renderers/CanvasTextRenderer.js';
-export * from '../src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
-export * from '../src/core/text-rendering/font-face-types/TrFontFace.js';
-export * from '../src/core/text-rendering/font-face-types/WebTrFontFace.js';
-export * from '../src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js';
-
-// Core Extensions
-export * from '../src/core/CoreExtension.js';
-
-// Stage (type only for Core Extensions)
-export type * from '../src/core/Stage.js';
diff --git a/exports/index.ts b/exports/index.ts
index 449a2813..f59d4e2f 100644
--- a/exports/index.ts
+++ b/exports/index.ts
@@ -17,6 +17,71 @@
* limitations under the License.
*/
-export * from './main-api.js';
-export * from './core-api.js';
-export * from './utils.js';
+/**
+ * Lightning 3 Renderer API
+ *
+ * @remarks
+ * This module exports the API for the Lightning 3 Renderer. You
+ * can import the exports from this module like so:
+ * ```ts
+ * import { Renderer } from '@lightning/renderer';
+ * ```
+ *
+ * Generally developers/frameworks using the Renderer will use the Main API to
+ * render applications.
+ *
+ * Do not confuse the Main API with the Core API which is used to extend
+ * capabilities of the Renderer. The Main API code always runs from the main
+ * thread.
+ *
+ * @module
+ */
+
+export * from '../src/main-api/INode.js';
+export * from '../src/main-api/Renderer.js';
+export * from '../src/main-api/ShaderController.js';
+export * from '../src/main-api/DynamicShaderController.js';
+export * from '../src/common/IAnimationController.js';
+export * from '../src/common/CommonTypes.js';
+
+// Selected types exported from the Core Renderer that can be used in the
+// context of the main API.
+export {
+ CoreTextureManager,
+ type TextureMap,
+} from '../src/core/CoreTextureManager.js';
+export type { MemoryInfo } from '../src/core/TextureMemoryManager.js';
+export type { ShaderMap, EffectMap } from '../src/core/CoreShaderManager.js';
+export type { TextRendererMap } from '../src/core/text-rendering/renderers/TextRenderer.js';
+export type { TrFontFaceMap } from '../src/core/text-rendering/font-face-types/TrFontFace.js';
+export type { AnimationSettings } from '../src/core/animations/CoreAnimation.js';
+export type {
+ EffectProps,
+ FadeOutEffectProps,
+ LinearGradientEffectProps,
+ RadialGradientEffectProps,
+ GrayscaleEffectProps,
+ GlitchEffectProps,
+ RadialProgressEffectProps,
+} from '../src/core/CoreShaderManager.js';
+export type { WebGlCoreRenderer } from '../src/core/renderers/webgl/WebGlCoreRenderer.js';
+export type { WebGlCoreCtxTexture } from '../src/core/renderers/webgl/WebGlCoreCtxTexture.js';
+
+// Shaders
+export * from '../src/core/renderers/webgl/WebGlCoreShader.js';
+export * from '../src/core/renderers/webgl/shaders/effects/ShaderEffect.js';
+export type { ShaderProgramSources } from '../src/core/renderers/webgl/internal/ShaderUtils.js';
+
+// Textures
+export * from '../src/core/textures/Texture.js';
+
+// Text Rendering & Fonts
+export * from '../src/core/text-rendering/renderers/TextRenderer.js';
+export * from '../src/core/text-rendering/renderers/CanvasTextRenderer.js';
+export * from '../src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
+export * from '../src/core/text-rendering/font-face-types/TrFontFace.js';
+export * from '../src/core/text-rendering/font-face-types/WebTrFontFace.js';
+export * from '../src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js';
+
+// Stage (type only for Core Extensions)
+export type * from '../src/core/Stage.js';
diff --git a/exports/main-api.ts b/exports/main-api.ts
deleted file mode 100644
index e1103907..00000000
--- a/exports/main-api.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * If not stated otherwise in this file or this component's LICENSE file the
- * following copyright and licenses apply:
- *
- * Copyright 2023 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Lightning 3 Renderer Main API
- *
- * @remarks
- * This module exports the Main API for the Lightning 3 Renderer. You
- * can import the exports from this module like so:
- * ```ts
- * import { RendererMain } from '@lightning/renderer';
- * ```
- *
- * Generally developers/frameworks using the Renderer will use the Main API to
- * render applications.
- *
- * Do not confuse the Main API with the Core API which is used to extend
- * capabilities of the Renderer. The Main API code always runs from the main
- * thread.
- *
- * @module
- */
-export * from '../src/main-api/INode.js';
-export * from '../src/main-api/ICoreDriver.js';
-export * from '../src/main-api/RendererMain.js';
-export * from '../src/render-drivers/main/MainCoreDriver.js';
-export * from '../src/render-drivers/threadx/ThreadXCoreDriver.js';
-export * from '../src/common/IAnimationController.js';
-export * from '../src/common/CommonTypes.js';
-
-// Selected types exported from the Core Renderer that can be used in the
-// context of the main API.
-export type { TextRendererMap } from '../src/core/text-rendering/renderers/TextRenderer.js';
-export type { TrFontFaceMap } from '../src/core/text-rendering/font-face-types/TrFontFace.js';
-export type { AnimationSettings } from '../src/core/animations/CoreAnimation.js';
-export type {
- EffectMap,
- EffectProps,
- FadeOutEffectProps,
- LinearGradientEffectProps,
- RadialGradientEffectProps,
- GrayscaleEffectProps,
- GlitchEffectProps,
- RadialProgressEffectProps,
- HolePunchEffectProps,
-} from '../src/core/CoreShaderManager.js';
diff --git a/exports/utils.ts b/exports/utils.ts
index 87650fa2..3f743c4f 100644
--- a/exports/utils.ts
+++ b/exports/utils.ts
@@ -38,4 +38,5 @@
* @packageDocumentation
*/
export { assertTruthy, mergeColorAlpha, deg2Rad } from '../src/utils.js';
+export { getNormalizedRgbaComponents } from '../src/core/lib/utils.js';
export { EventEmitter } from '../src/common/EventEmitter.js';
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 85f6b7fa..00000000
--- a/package-lock.json
+++ /dev/null
@@ -1,6102 +0,0 @@
-{
- "name": "@lightningjs/renderer",
- "version": "0.9.4",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "name": "@lightningjs/renderer",
- "version": "0.9.4",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@lightningjs/threadx": "^0.3.4",
- "@protobufjs/eventemitter": "^1.1.0",
- "memize": "^2.1.0"
- },
- "devDependencies": {
- "@types/node": "^18.14.6",
- "@typescript-eslint/eslint-plugin": "^5.55.0",
- "@typescript-eslint/parser": "^5.55.0",
- "concurrently": "^8.0.1",
- "eslint": "^8.35.0",
- "eslint-config-prettier": "^8.7.0",
- "husky": "^8.0.3",
- "lint-staged": "^13.2.0",
- "prettier": "^2.8.4",
- "typedoc": "^0.25.1",
- "typescript": "^5.2.2",
- "vitest": "^0.34.2"
- },
- "engines": {
- "node": ">= 20.9.0",
- "npm": ">= 10.0.0",
- "pnpm": ">= 8.9.2"
- }
- },
- "node_modules/@aashutoshrathi/word-wrap": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
- "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.23.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
- "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
- "dev": true,
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@eslint-community/eslint-utils": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
- "dev": true,
- "dependencies": {
- "eslint-visitor-keys": "^3.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
- }
- },
- "node_modules/@eslint-community/regexpp": {
- "version": "4.9.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
- "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
- "dev": true,
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/@eslint/eslintrc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
- "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.6.0",
- "globals": "^13.19.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@eslint/js": {
- "version": "8.52.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz",
- "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.11.13",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
- "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
- "dev": true,
- "dependencies": {
- "@humanwhocodes/object-schema": "^2.0.1",
- "debug": "^4.1.1",
- "minimatch": "^3.0.5"
- },
- "engines": {
- "node": ">=10.10.0"
- }
- },
- "node_modules/@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true,
- "engines": {
- "node": ">=12.22"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@humanwhocodes/object-schema": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
- "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
- "dev": true
- },
- "node_modules/@jest/schemas": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
- "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
- "dev": true,
- "dependencies": {
- "@sinclair/typebox": "^0.27.8"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "dev": true
- },
- "node_modules/@lightningjs/threadx": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@lightningjs/threadx/-/threadx-0.3.4.tgz",
- "integrity": "sha512-x9ylADrRxSrIczcMHgkNYpmnvoPvWKuasxmEf3dnixazpYJCw9HLoWNOi2UsD0U4oEL/tMQZA0sZbO7VVGMTag=="
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
- },
- "node_modules/@sinclair/typebox": {
- "version": "0.27.8",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
- "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
- "dev": true
- },
- "node_modules/@types/chai": {
- "version": "4.3.9",
- "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz",
- "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==",
- "dev": true
- },
- "node_modules/@types/chai-subset": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz",
- "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==",
- "dev": true,
- "dependencies": {
- "@types/chai": "*"
- }
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.14",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz",
- "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==",
- "dev": true
- },
- "node_modules/@types/node": {
- "version": "18.18.6",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
- "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
- "dev": true
- },
- "node_modules/@types/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
- "dev": true
- },
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
- "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
- "dev": true,
- "dependencies": {
- "@eslint-community/regexpp": "^4.4.0",
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/type-utils": "5.62.0",
- "@typescript-eslint/utils": "5.62.0",
- "debug": "^4.3.4",
- "graphemer": "^1.4.0",
- "ignore": "^5.2.0",
- "natural-compare-lite": "^1.4.0",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^5.0.0",
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/parser": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
- "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/typescript-estree": "5.62.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
- "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/visitor-keys": "5.62.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
- "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/typescript-estree": "5.62.0",
- "@typescript-eslint/utils": "5.62.0",
- "debug": "^4.3.4",
- "tsutils": "^3.21.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "*"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/types": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
- "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
- "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/visitor-keys": "5.62.0",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/utils": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
- "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@types/json-schema": "^7.0.9",
- "@types/semver": "^7.3.12",
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/typescript-estree": "5.62.0",
- "eslint-scope": "^5.1.1",
- "semver": "^7.3.7"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
- "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "5.62.0",
- "eslint-visitor-keys": "^3.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@ungap/structured-clone": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
- "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
- "dev": true
- },
- "node_modules/@vitest/expect": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz",
- "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==",
- "dev": true,
- "dependencies": {
- "@vitest/spy": "0.34.6",
- "@vitest/utils": "0.34.6",
- "chai": "^4.3.10"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/runner": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz",
- "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==",
- "dev": true,
- "dependencies": {
- "@vitest/utils": "0.34.6",
- "p-limit": "^4.0.0",
- "pathe": "^1.1.1"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/runner/node_modules/p-limit": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
- "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
- "dev": true,
- "dependencies": {
- "yocto-queue": "^1.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@vitest/runner/node_modules/yocto-queue": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
- "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
- "dev": true,
- "engines": {
- "node": ">=12.20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@vitest/snapshot": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz",
- "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==",
- "dev": true,
- "dependencies": {
- "magic-string": "^0.30.1",
- "pathe": "^1.1.1",
- "pretty-format": "^29.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/spy": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz",
- "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==",
- "dev": true,
- "dependencies": {
- "tinyspy": "^2.1.1"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/utils": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz",
- "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==",
- "dev": true,
- "dependencies": {
- "diff-sequences": "^29.4.3",
- "loupe": "^2.3.6",
- "pretty-format": "^29.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/acorn": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
- "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/acorn-walk": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
- "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ansi-escapes": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz",
- "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==",
- "dev": true,
- "dependencies": {
- "type-fest": "^1.0.2"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-escapes/node_modules/type-fest": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
- "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-sequence-parser": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz",
- "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==",
- "dev": true
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "dependencies": {
- "fill-range": "^7.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cac": {
- "version": "6.7.14",
- "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/chai": {
- "version": "4.3.10",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz",
- "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==",
- "dev": true,
- "dependencies": {
- "assertion-error": "^1.1.0",
- "check-error": "^1.0.3",
- "deep-eql": "^4.1.3",
- "get-func-name": "^2.0.2",
- "loupe": "^2.3.6",
- "pathval": "^1.1.1",
- "type-detect": "^4.0.8"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/chalk/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/check-error": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
- "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
- "dev": true,
- "dependencies": {
- "get-func-name": "^2.0.2"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/cli-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
- "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
- "dev": true,
- "dependencies": {
- "restore-cursor": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cli-truncate": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz",
- "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==",
- "dev": true,
- "dependencies": {
- "slice-ansi": "^5.0.0",
- "string-width": "^5.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cliui/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/cliui/node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "node_modules/colorette": {
- "version": "2.0.20",
- "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
- "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
- "dev": true
- },
- "node_modules/commander": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz",
- "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==",
- "dev": true,
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "node_modules/concurrently": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz",
- "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.1.2",
- "date-fns": "^2.30.0",
- "lodash": "^4.17.21",
- "rxjs": "^7.8.1",
- "shell-quote": "^1.8.1",
- "spawn-command": "0.0.2",
- "supports-color": "^8.1.1",
- "tree-kill": "^1.2.2",
- "yargs": "^17.7.2"
- },
- "bin": {
- "conc": "dist/bin/concurrently.js",
- "concurrently": "dist/bin/concurrently.js"
- },
- "engines": {
- "node": "^14.13.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
- }
- },
- "node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "dev": true,
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/date-fns": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
- "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
- "dev": true,
- "dependencies": {
- "@babel/runtime": "^7.21.0"
- },
- "engines": {
- "node": ">=0.11"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/date-fns"
- }
- },
- "node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/deep-eql": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
- "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
- "dev": true,
- "dependencies": {
- "type-detect": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true
- },
- "node_modules/diff-sequences": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
- "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
- "dev": true,
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "dependencies": {
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
- },
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
- },
- "node_modules/esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
- }
- },
- "node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint": {
- "version": "8.52.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz",
- "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.2",
- "@eslint/js": "8.52.0",
- "@humanwhocodes/config-array": "^0.11.13",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@nodelib/fs.walk": "^1.2.8",
- "@ungap/structured-clone": "^1.2.0",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.3.2",
- "doctrine": "^3.0.0",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.3",
- "espree": "^9.6.1",
- "esquery": "^1.4.2",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "globals": "^13.19.0",
- "graphemer": "^1.4.0",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "is-path-inside": "^3.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.3",
- "strip-ansi": "^6.0.1",
- "text-table": "^0.2.0"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-config-prettier": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
- "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
- "dev": true,
- "bin": {
- "eslint-config-prettier": "bin/cli.js"
- },
- "peerDependencies": {
- "eslint": ">=7.0.0"
- }
- },
- "node_modules/eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
- "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint/node_modules/eslint-scope": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
- "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
- "dev": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/espree": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
- "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.9.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.4.1"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
- "dev": true,
- "dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/esquery/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esrecurse/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eventemitter3": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
- "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
- "dev": true
- },
- "node_modules/execa": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
- "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
- "dev": true,
- "dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^6.0.1",
- "human-signals": "^4.3.0",
- "is-stream": "^3.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^5.1.0",
- "onetime": "^6.0.0",
- "signal-exit": "^3.0.7",
- "strip-final-newline": "^3.0.0"
- },
- "engines": {
- "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "node_modules/fast-glob": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true
- },
- "node_modules/fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
- "dev": true,
- "dependencies": {
- "flat-cache": "^3.0.4"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/flat-cache": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
- "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
- "dev": true,
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.3",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/flatted": {
- "version": "3.2.9",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
- "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
- "dev": true
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-func-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
- "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/get-stream": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
- "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/globals": {
- "version": "13.23.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
- "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
- "dev": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/graphemer": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
- "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/human-signals": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
- "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
- "dev": true,
- "engines": {
- "node": ">=14.18.0"
- }
- },
- "node_modules/husky": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
- "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
- "dev": true,
- "bin": {
- "husky": "lib/bin.js"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/typicode"
- }
- },
- "node_modules/ignore": {
- "version": "5.2.4",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
- "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "dev": true,
- "dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
- "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
- "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
- "dev": true,
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
- },
- "node_modules/jsonc-parser": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
- "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
- "dev": true
- },
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
- "dependencies": {
- "json-buffer": "3.0.1"
- }
- },
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/lilconfig": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/lint-staged": {
- "version": "13.3.0",
- "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz",
- "integrity": "sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ==",
- "dev": true,
- "dependencies": {
- "chalk": "5.3.0",
- "commander": "11.0.0",
- "debug": "4.3.4",
- "execa": "7.2.0",
- "lilconfig": "2.1.0",
- "listr2": "6.6.1",
- "micromatch": "4.0.5",
- "pidtree": "0.6.0",
- "string-argv": "0.3.2",
- "yaml": "2.3.1"
- },
- "bin": {
- "lint-staged": "bin/lint-staged.js"
- },
- "engines": {
- "node": "^16.14.0 || >=18.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/lint-staged"
- }
- },
- "node_modules/lint-staged/node_modules/chalk": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
- "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
- "dev": true,
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/listr2": {
- "version": "6.6.1",
- "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz",
- "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==",
- "dev": true,
- "dependencies": {
- "cli-truncate": "^3.1.0",
- "colorette": "^2.0.20",
- "eventemitter3": "^5.0.1",
- "log-update": "^5.0.1",
- "rfdc": "^1.3.0",
- "wrap-ansi": "^8.1.0"
- },
- "engines": {
- "node": ">=16.0.0"
- },
- "peerDependencies": {
- "enquirer": ">= 2.3.0 < 3"
- },
- "peerDependenciesMeta": {
- "enquirer": {
- "optional": true
- }
- }
- },
- "node_modules/local-pkg": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
- "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
- "dev": true,
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
- },
- "node_modules/log-update": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz",
- "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==",
- "dev": true,
- "dependencies": {
- "ansi-escapes": "^5.0.0",
- "cli-cursor": "^4.0.0",
- "slice-ansi": "^5.0.0",
- "strip-ansi": "^7.0.1",
- "wrap-ansi": "^8.0.1"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-update/node_modules/ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/log-update/node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/loupe": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
- "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
- "dev": true,
- "dependencies": {
- "get-func-name": "^2.0.1"
- }
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/lunr": {
- "version": "2.3.9",
- "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
- "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
- "dev": true
- },
- "node_modules/magic-string": {
- "version": "0.30.5",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
- "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==",
- "dev": true,
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.4.15"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/marked": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
- "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
- "dev": true,
- "bin": {
- "marked": "bin/marked.js"
- },
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/memize": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/memize/-/memize-2.1.0.tgz",
- "integrity": "sha512-yywVJy8ctVlN5lNPxsep5urnZ6TTclwPEyigM9M3Bi8vseJBOfqNrGWN/r8NzuIt3PovM323W04blJfGQfQSVg=="
- },
- "node_modules/merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mimic-fn": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
- "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/mlly": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz",
- "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.10.0",
- "pathe": "^1.1.1",
- "pkg-types": "^1.0.3",
- "ufo": "^1.3.0"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "node_modules/nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true
- },
- "node_modules/natural-compare-lite": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
- "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
- "dev": true
- },
- "node_modules/npm-run-path": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
- "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
- "dev": true,
- "dependencies": {
- "path-key": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/npm-run-path/node_modules/path-key": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
- "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/onetime": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
- "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
- "dev": true,
- "dependencies": {
- "mimic-fn": "^4.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/optionator": {
- "version": "0.9.3",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
- "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
- "dev": true,
- "dependencies": {
- "@aashutoshrathi/word-wrap": "^1.2.3",
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/pathe": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz",
- "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==",
- "dev": true
- },
- "node_modules/pathval": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
- "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pidtree": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
- "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
- "dev": true,
- "bin": {
- "pidtree": "bin/pidtree.js"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/pkg-types": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
- "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==",
- "dev": true,
- "dependencies": {
- "jsonc-parser": "^3.2.0",
- "mlly": "^1.2.0",
- "pathe": "^1.1.0"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.31",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
- "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true,
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/prettier": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
- "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
- "dev": true,
- "bin": {
- "prettier": "bin-prettier.js"
- },
- "engines": {
- "node": ">=10.13.0"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
- "node_modules/pretty-format": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
- "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.6.3",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/pretty-format/node_modules/ansi-styles": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
- "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/punycode": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
- "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/react-is": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
- "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
- "dev": true
- },
- "node_modules/regenerator-runtime": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
- "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
- "dev": true
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/restore-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
- "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
- "dev": true,
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/restore-cursor/node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/restore-cursor/node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rfdc": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
- "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
- "dev": true
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/rollup": {
- "version": "3.29.4",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
- "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
- "dev": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=14.18.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
- "node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shell-quote": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
- "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/shiki": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz",
- "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==",
- "dev": true,
- "dependencies": {
- "ansi-sequence-parser": "^1.1.0",
- "jsonc-parser": "^3.2.0",
- "vscode-oniguruma": "^1.7.0",
- "vscode-textmate": "^8.0.0"
- }
- },
- "node_modules/siginfo": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
- "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
- "dev": true
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
- },
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/slice-ansi": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
- "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^6.0.0",
- "is-fullwidth-code-point": "^4.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/slice-ansi?sponsor=1"
- }
- },
- "node_modules/slice-ansi/node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/spawn-command": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz",
- "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==",
- "dev": true
- },
- "node_modules/stackback": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
- "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
- "dev": true
- },
- "node_modules/std-env": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.3.tgz",
- "integrity": "sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==",
- "dev": true
- },
- "node_modules/string-argv": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
- "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
- "dev": true,
- "engines": {
- "node": ">=0.6.19"
- }
- },
- "node_modules/string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
- "dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/string-width/node_modules/ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/string-width/node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-final-newline": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
- "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/strip-literal": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz",
- "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.10.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
- },
- "node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "node_modules/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
- },
- "node_modules/tinybench": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz",
- "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==",
- "dev": true
- },
- "node_modules/tinypool": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz",
- "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==",
- "dev": true,
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/tinyspy": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz",
- "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==",
- "dev": true,
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/tree-kill": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
- "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
- "dev": true,
- "bin": {
- "tree-kill": "cli.js"
- }
- },
- "node_modules/tslib": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
- "dev": true
- },
- "node_modules/tsutils": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
- "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
- "dev": true,
- "dependencies": {
- "tslib": "^1.8.1"
- },
- "engines": {
- "node": ">= 6"
- },
- "peerDependencies": {
- "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
- }
- },
- "node_modules/tsutils/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "dev": true
- },
- "node_modules/type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "dependencies": {
- "prelude-ls": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/typedoc": {
- "version": "0.25.2",
- "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.2.tgz",
- "integrity": "sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==",
- "dev": true,
- "dependencies": {
- "lunr": "^2.3.9",
- "marked": "^4.3.0",
- "minimatch": "^9.0.3",
- "shiki": "^0.14.1"
- },
- "bin": {
- "typedoc": "bin/typedoc"
- },
- "engines": {
- "node": ">= 16"
- },
- "peerDependencies": {
- "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x"
- }
- },
- "node_modules/typedoc/node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/typedoc/node_modules/minimatch": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
- "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/typescript": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
- "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
- "dev": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/ufo": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz",
- "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==",
- "dev": true
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/vite": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz",
- "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.18.10",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "@types/node": ">= 14",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/vite-node": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz",
- "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==",
- "dev": true,
- "dependencies": {
- "cac": "^6.7.14",
- "debug": "^4.3.4",
- "mlly": "^1.4.0",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
- },
- "bin": {
- "vite-node": "vite-node.mjs"
- },
- "engines": {
- "node": ">=v14.18.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/vitest": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz",
- "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==",
- "dev": true,
- "dependencies": {
- "@types/chai": "^4.3.5",
- "@types/chai-subset": "^1.3.3",
- "@types/node": "*",
- "@vitest/expect": "0.34.6",
- "@vitest/runner": "0.34.6",
- "@vitest/snapshot": "0.34.6",
- "@vitest/spy": "0.34.6",
- "@vitest/utils": "0.34.6",
- "acorn": "^8.9.0",
- "acorn-walk": "^8.2.0",
- "cac": "^6.7.14",
- "chai": "^4.3.10",
- "debug": "^4.3.4",
- "local-pkg": "^0.4.3",
- "magic-string": "^0.30.1",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "std-env": "^3.3.3",
- "strip-literal": "^1.0.1",
- "tinybench": "^2.5.0",
- "tinypool": "^0.7.0",
- "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0",
- "vite-node": "0.34.6",
- "why-is-node-running": "^2.2.2"
- },
- "bin": {
- "vitest": "vitest.mjs"
- },
- "engines": {
- "node": ">=v14.18.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- },
- "peerDependencies": {
- "@edge-runtime/vm": "*",
- "@vitest/browser": "*",
- "@vitest/ui": "*",
- "happy-dom": "*",
- "jsdom": "*",
- "playwright": "*",
- "safaridriver": "*",
- "webdriverio": "*"
- },
- "peerDependenciesMeta": {
- "@edge-runtime/vm": {
- "optional": true
- },
- "@vitest/browser": {
- "optional": true
- },
- "@vitest/ui": {
- "optional": true
- },
- "happy-dom": {
- "optional": true
- },
- "jsdom": {
- "optional": true
- },
- "playwright": {
- "optional": true
- },
- "safaridriver": {
- "optional": true
- },
- "webdriverio": {
- "optional": true
- }
- }
- },
- "node_modules/vscode-oniguruma": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
- "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==",
- "dev": true
- },
- "node_modules/vscode-textmate": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
- "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
- "dev": true
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/why-is-node-running": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
- "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
- "dev": true,
- "dependencies": {
- "siginfo": "^2.0.0",
- "stackback": "0.0.2"
- },
- "bin": {
- "why-is-node-running": "cli.js"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- },
- "node_modules/yaml": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz",
- "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==",
- "dev": true,
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/yargs/node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- }
- },
- "dependencies": {
- "@aashutoshrathi/word-wrap": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
- "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
- "dev": true
- },
- "@babel/runtime": {
- "version": "7.23.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
- "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
- "dev": true,
- "requires": {
- "regenerator-runtime": "^0.14.0"
- }
- },
- "@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "dev": true,
- "optional": true
- },
- "@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "dev": true,
- "optional": true
- },
- "@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "dev": true,
- "optional": true
- },
- "@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "dev": true,
- "optional": true
- },
- "@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "dev": true,
- "optional": true
- },
- "@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "dev": true,
- "optional": true
- },
- "@eslint-community/eslint-utils": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^3.3.0"
- }
- },
- "@eslint-community/regexpp": {
- "version": "4.9.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
- "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
- "dev": true
- },
- "@eslint/eslintrc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
- "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
- "dev": true,
- "requires": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.6.0",
- "globals": "^13.19.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- }
- },
- "@eslint/js": {
- "version": "8.52.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz",
- "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==",
- "dev": true
- },
- "@humanwhocodes/config-array": {
- "version": "0.11.13",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
- "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
- "dev": true,
- "requires": {
- "@humanwhocodes/object-schema": "^2.0.1",
- "debug": "^4.1.1",
- "minimatch": "^3.0.5"
- }
- },
- "@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true
- },
- "@humanwhocodes/object-schema": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
- "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
- "dev": true
- },
- "@jest/schemas": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
- "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
- "dev": true,
- "requires": {
- "@sinclair/typebox": "^0.27.8"
- }
- },
- "@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "dev": true
- },
- "@lightningjs/threadx": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@lightningjs/threadx/-/threadx-0.3.4.tgz",
- "integrity": "sha512-x9ylADrRxSrIczcMHgkNYpmnvoPvWKuasxmEf3dnixazpYJCw9HLoWNOi2UsD0U4oEL/tMQZA0sZbO7VVGMTag=="
- },
- "@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "requires": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- }
- },
- "@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true
- },
- "@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "requires": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- }
- },
- "@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
- },
- "@sinclair/typebox": {
- "version": "0.27.8",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
- "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
- "dev": true
- },
- "@types/chai": {
- "version": "4.3.9",
- "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz",
- "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==",
- "dev": true
- },
- "@types/chai-subset": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz",
- "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==",
- "dev": true,
- "requires": {
- "@types/chai": "*"
- }
- },
- "@types/json-schema": {
- "version": "7.0.14",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz",
- "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==",
- "dev": true
- },
- "@types/node": {
- "version": "18.18.6",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
- "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
- "dev": true
- },
- "@types/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
- "dev": true
- },
- "@typescript-eslint/eslint-plugin": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
- "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
- "dev": true,
- "requires": {
- "@eslint-community/regexpp": "^4.4.0",
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/type-utils": "5.62.0",
- "@typescript-eslint/utils": "5.62.0",
- "debug": "^4.3.4",
- "graphemer": "^1.4.0",
- "ignore": "^5.2.0",
- "natural-compare-lite": "^1.4.0",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- }
- },
- "@typescript-eslint/parser": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
- "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
- "dev": true,
- "requires": {
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/typescript-estree": "5.62.0",
- "debug": "^4.3.4"
- }
- },
- "@typescript-eslint/scope-manager": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
- "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
- "dev": true,
- "requires": {
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/visitor-keys": "5.62.0"
- }
- },
- "@typescript-eslint/type-utils": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
- "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
- "dev": true,
- "requires": {
- "@typescript-eslint/typescript-estree": "5.62.0",
- "@typescript-eslint/utils": "5.62.0",
- "debug": "^4.3.4",
- "tsutils": "^3.21.0"
- }
- },
- "@typescript-eslint/types": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
- "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
- "dev": true
- },
- "@typescript-eslint/typescript-estree": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
- "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
- "dev": true,
- "requires": {
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/visitor-keys": "5.62.0",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- }
- },
- "@typescript-eslint/utils": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
- "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
- "dev": true,
- "requires": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@types/json-schema": "^7.0.9",
- "@types/semver": "^7.3.12",
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/typescript-estree": "5.62.0",
- "eslint-scope": "^5.1.1",
- "semver": "^7.3.7"
- }
- },
- "@typescript-eslint/visitor-keys": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
- "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
- "dev": true,
- "requires": {
- "@typescript-eslint/types": "5.62.0",
- "eslint-visitor-keys": "^3.3.0"
- }
- },
- "@ungap/structured-clone": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
- "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
- "dev": true
- },
- "@vitest/expect": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz",
- "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==",
- "dev": true,
- "requires": {
- "@vitest/spy": "0.34.6",
- "@vitest/utils": "0.34.6",
- "chai": "^4.3.10"
- }
- },
- "@vitest/runner": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz",
- "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==",
- "dev": true,
- "requires": {
- "@vitest/utils": "0.34.6",
- "p-limit": "^4.0.0",
- "pathe": "^1.1.1"
- },
- "dependencies": {
- "p-limit": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
- "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
- "dev": true,
- "requires": {
- "yocto-queue": "^1.0.0"
- }
- },
- "yocto-queue": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
- "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
- "dev": true
- }
- }
- },
- "@vitest/snapshot": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz",
- "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==",
- "dev": true,
- "requires": {
- "magic-string": "^0.30.1",
- "pathe": "^1.1.1",
- "pretty-format": "^29.5.0"
- }
- },
- "@vitest/spy": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz",
- "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==",
- "dev": true,
- "requires": {
- "tinyspy": "^2.1.1"
- }
- },
- "@vitest/utils": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz",
- "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==",
- "dev": true,
- "requires": {
- "diff-sequences": "^29.4.3",
- "loupe": "^2.3.6",
- "pretty-format": "^29.5.0"
- }
- },
- "acorn": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
- "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
- "dev": true
- },
- "acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "requires": {}
- },
- "acorn-walk": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
- "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
- "dev": true
- },
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "ansi-escapes": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz",
- "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==",
- "dev": true,
- "requires": {
- "type-fest": "^1.0.2"
- },
- "dependencies": {
- "type-fest": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
- "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
- "dev": true
- }
- }
- },
- "ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
- },
- "ansi-sequence-parser": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz",
- "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==",
- "dev": true
- },
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true
- },
- "assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
- "dev": true
- },
- "balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "requires": {
- "fill-range": "^7.0.1"
- }
- },
- "cac": {
- "version": "6.7.14",
- "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
- "dev": true
- },
- "callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true
- },
- "chai": {
- "version": "4.3.10",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz",
- "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==",
- "dev": true,
- "requires": {
- "assertion-error": "^1.1.0",
- "check-error": "^1.0.3",
- "deep-eql": "^4.1.3",
- "get-func-name": "^2.0.2",
- "loupe": "^2.3.6",
- "pathval": "^1.1.1",
- "type-detect": "^4.0.8"
- }
- },
- "chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "check-error": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
- "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
- "dev": true,
- "requires": {
- "get-func-name": "^2.0.2"
- }
- },
- "cli-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
- "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
- "dev": true,
- "requires": {
- "restore-cursor": "^4.0.0"
- }
- },
- "cli-truncate": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz",
- "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==",
- "dev": true,
- "requires": {
- "slice-ansi": "^5.0.0",
- "string-width": "^5.0.0"
- }
- },
- "cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "requires": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "dependencies": {
- "emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
- },
- "string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- }
- },
- "wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- }
- }
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "colorette": {
- "version": "2.0.20",
- "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
- "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
- "dev": true
- },
- "commander": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz",
- "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==",
- "dev": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "concurrently": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz",
- "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==",
- "dev": true,
- "requires": {
- "chalk": "^4.1.2",
- "date-fns": "^2.30.0",
- "lodash": "^4.17.21",
- "rxjs": "^7.8.1",
- "shell-quote": "^1.8.1",
- "spawn-command": "0.0.2",
- "supports-color": "^8.1.1",
- "tree-kill": "^1.2.2",
- "yargs": "^17.7.2"
- }
- },
- "cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "dev": true,
- "requires": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- }
- },
- "date-fns": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
- "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
- "dev": true,
- "requires": {
- "@babel/runtime": "^7.21.0"
- }
- },
- "debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "deep-eql": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
- "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
- "dev": true,
- "requires": {
- "type-detect": "^4.0.0"
- }
- },
- "deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true
- },
- "diff-sequences": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
- "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
- "dev": true
- },
- "dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "requires": {
- "path-type": "^4.0.0"
- }
- },
- "doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
- "eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
- },
- "emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
- },
- "esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "requires": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
- }
- },
- "escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true
- },
- "escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true
- },
- "eslint": {
- "version": "8.52.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz",
- "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==",
- "dev": true,
- "requires": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.2",
- "@eslint/js": "8.52.0",
- "@humanwhocodes/config-array": "^0.11.13",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@nodelib/fs.walk": "^1.2.8",
- "@ungap/structured-clone": "^1.2.0",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.3.2",
- "doctrine": "^3.0.0",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.3",
- "espree": "^9.6.1",
- "esquery": "^1.4.2",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "globals": "^13.19.0",
- "graphemer": "^1.4.0",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "is-path-inside": "^3.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.3",
- "strip-ansi": "^6.0.1",
- "text-table": "^0.2.0"
- },
- "dependencies": {
- "eslint-scope": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
- "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- }
- },
- "estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true
- }
- }
- },
- "eslint-config-prettier": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
- "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
- "dev": true,
- "requires": {}
- },
- "eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
- "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- }
- },
- "eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true
- },
- "espree": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
- "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
- "dev": true,
- "requires": {
- "acorn": "^8.9.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.4.1"
- }
- },
- "esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
- "dev": true,
- "requires": {
- "estraverse": "^5.1.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true
- }
- }
- },
- "esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "requires": {
- "estraverse": "^5.2.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true
- }
- }
- },
- "estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true
- },
- "esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true
- },
- "eventemitter3": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
- "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
- "dev": true
- },
- "execa": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
- "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
- "dev": true,
- "requires": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^6.0.1",
- "human-signals": "^4.3.0",
- "is-stream": "^3.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^5.1.0",
- "onetime": "^6.0.0",
- "signal-exit": "^3.0.7",
- "strip-final-newline": "^3.0.0"
- }
- },
- "fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "fast-glob": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
- "dev": true,
- "requires": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "dependencies": {
- "glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.1"
- }
- }
- }
- },
- "fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true
- },
- "fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "requires": {
- "reusify": "^1.0.4"
- }
- },
- "file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
- "dev": true,
- "requires": {
- "flat-cache": "^3.0.4"
- }
- },
- "fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "requires": {
- "to-regex-range": "^5.0.1"
- }
- },
- "find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "requires": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- }
- },
- "flat-cache": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
- "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
- "dev": true,
- "requires": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.3",
- "rimraf": "^3.0.2"
- }
- },
- "flatted": {
- "version": "3.2.9",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
- "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
- "dev": true
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "optional": true
- },
- "get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
- },
- "get-func-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
- "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
- "dev": true
- },
- "get-stream": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
- "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
- "dev": true
- },
- "glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.3"
- }
- },
- "globals": {
- "version": "13.23.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
- "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
- "dev": true,
- "requires": {
- "type-fest": "^0.20.2"
- }
- },
- "globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "requires": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- }
- },
- "graphemer": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
- "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
- },
- "human-signals": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
- "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
- "dev": true
- },
- "husky": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
- "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
- "dev": true
- },
- "ignore": {
- "version": "5.2.4",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
- "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
- "dev": true
- },
- "import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "dev": true,
- "requires": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
- "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
- "dev": true
- },
- "is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
- },
- "is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true
- },
- "is-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
- "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
- "dev": true
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "requires": {
- "argparse": "^2.0.1"
- }
- },
- "json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
- },
- "jsonc-parser": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
- "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
- "dev": true
- },
- "keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
- "requires": {
- "json-buffer": "3.0.1"
- }
- },
- "levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- }
- },
- "lilconfig": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
- "dev": true
- },
- "lint-staged": {
- "version": "13.3.0",
- "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz",
- "integrity": "sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ==",
- "dev": true,
- "requires": {
- "chalk": "5.3.0",
- "commander": "11.0.0",
- "debug": "4.3.4",
- "execa": "7.2.0",
- "lilconfig": "2.1.0",
- "listr2": "6.6.1",
- "micromatch": "4.0.5",
- "pidtree": "0.6.0",
- "string-argv": "0.3.2",
- "yaml": "2.3.1"
- },
- "dependencies": {
- "chalk": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
- "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
- "dev": true
- }
- }
- },
- "listr2": {
- "version": "6.6.1",
- "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz",
- "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==",
- "dev": true,
- "requires": {
- "cli-truncate": "^3.1.0",
- "colorette": "^2.0.20",
- "eventemitter3": "^5.0.1",
- "log-update": "^5.0.1",
- "rfdc": "^1.3.0",
- "wrap-ansi": "^8.1.0"
- }
- },
- "local-pkg": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
- "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
- "dev": true
- },
- "locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "requires": {
- "p-locate": "^5.0.0"
- }
- },
- "lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
- },
- "lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
- },
- "log-update": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz",
- "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==",
- "dev": true,
- "requires": {
- "ansi-escapes": "^5.0.0",
- "cli-cursor": "^4.0.0",
- "slice-ansi": "^5.0.0",
- "strip-ansi": "^7.0.1",
- "wrap-ansi": "^8.0.1"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true
- },
- "strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "requires": {
- "ansi-regex": "^6.0.1"
- }
- }
- }
- },
- "loupe": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
- "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
- "dev": true,
- "requires": {
- "get-func-name": "^2.0.1"
- }
- },
- "lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "lunr": {
- "version": "2.3.9",
- "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
- "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
- "dev": true
- },
- "magic-string": {
- "version": "0.30.5",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
- "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==",
- "dev": true,
- "requires": {
- "@jridgewell/sourcemap-codec": "^1.4.15"
- }
- },
- "marked": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
- "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
- "dev": true
- },
- "memize": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/memize/-/memize-2.1.0.tgz",
- "integrity": "sha512-yywVJy8ctVlN5lNPxsep5urnZ6TTclwPEyigM9M3Bi8vseJBOfqNrGWN/r8NzuIt3PovM323W04blJfGQfQSVg=="
- },
- "merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true
- },
- "merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true
- },
- "micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "requires": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- }
- },
- "mimic-fn": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
- "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
- "dev": true
- },
- "minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "mlly": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz",
- "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==",
- "dev": true,
- "requires": {
- "acorn": "^8.10.0",
- "pathe": "^1.1.1",
- "pkg-types": "^1.0.3",
- "ufo": "^1.3.0"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true
- },
- "natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true
- },
- "natural-compare-lite": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
- "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
- "dev": true
- },
- "npm-run-path": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
- "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
- "dev": true,
- "requires": {
- "path-key": "^4.0.0"
- },
- "dependencies": {
- "path-key": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
- "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "dev": true
- }
- }
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "onetime": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
- "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
- "dev": true,
- "requires": {
- "mimic-fn": "^4.0.0"
- }
- },
- "optionator": {
- "version": "0.9.3",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
- "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
- "dev": true,
- "requires": {
- "@aashutoshrathi/word-wrap": "^1.2.3",
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0"
- }
- },
- "p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "requires": {
- "yocto-queue": "^0.1.0"
- }
- },
- "p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "requires": {
- "p-limit": "^3.0.2"
- }
- },
- "parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "requires": {
- "callsites": "^3.0.0"
- }
- },
- "path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true
- },
- "path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true
- },
- "path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true
- },
- "pathe": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz",
- "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==",
- "dev": true
- },
- "pathval": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
- "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
- "dev": true
- },
- "picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true
- },
- "pidtree": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
- "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
- "dev": true
- },
- "pkg-types": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
- "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==",
- "dev": true,
- "requires": {
- "jsonc-parser": "^3.2.0",
- "mlly": "^1.2.0",
- "pathe": "^1.1.0"
- }
- },
- "postcss": {
- "version": "8.4.31",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
- "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
- "dev": true,
- "requires": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- }
- },
- "prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true
- },
- "prettier": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
- "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
- "dev": true
- },
- "pretty-format": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
- "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.6.3",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
- "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true
- }
- }
- },
- "punycode": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
- "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
- "dev": true
- },
- "queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true
- },
- "react-is": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
- "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
- "dev": true
- },
- "regenerator-runtime": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
- "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
- "dev": true
- },
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true
- },
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true
- },
- "restore-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
- "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
- "dev": true,
- "requires": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "dependencies": {
- "mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true
- },
- "onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "requires": {
- "mimic-fn": "^2.1.0"
- }
- }
- }
- },
- "reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true
- },
- "rfdc": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
- "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
- "dev": true
- },
- "rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "rollup": {
- "version": "3.29.4",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
- "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
- "dev": true,
- "requires": {
- "fsevents": "~2.3.2"
- }
- },
- "run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "requires": {
- "queue-microtask": "^1.2.2"
- }
- },
- "rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "requires": {
- "tslib": "^2.1.0"
- }
- },
- "semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "requires": {
- "shebang-regex": "^3.0.0"
- }
- },
- "shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true
- },
- "shell-quote": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
- "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
- "dev": true
- },
- "shiki": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz",
- "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==",
- "dev": true,
- "requires": {
- "ansi-sequence-parser": "^1.1.0",
- "jsonc-parser": "^3.2.0",
- "vscode-oniguruma": "^1.7.0",
- "vscode-textmate": "^8.0.0"
- }
- },
- "siginfo": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
- "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
- "dev": true
- },
- "signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
- },
- "slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true
- },
- "slice-ansi": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
- "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^6.0.0",
- "is-fullwidth-code-point": "^4.0.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true
- }
- }
- },
- "source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true
- },
- "spawn-command": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz",
- "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==",
- "dev": true
- },
- "stackback": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
- "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
- "dev": true
- },
- "std-env": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.3.tgz",
- "integrity": "sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==",
- "dev": true
- },
- "string-argv": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
- "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
- "dev": true
- },
- "string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
- "requires": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true
- },
- "strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "requires": {
- "ansi-regex": "^6.0.1"
- }
- }
- }
- },
- "strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.1"
- }
- },
- "strip-final-newline": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
- "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
- "dev": true
- },
- "strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true
- },
- "strip-literal": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz",
- "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==",
- "dev": true,
- "requires": {
- "acorn": "^8.10.0"
- }
- },
- "supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- },
- "text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
- },
- "tinybench": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz",
- "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==",
- "dev": true
- },
- "tinypool": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz",
- "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==",
- "dev": true
- },
- "tinyspy": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz",
- "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==",
- "dev": true
- },
- "to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "requires": {
- "is-number": "^7.0.0"
- }
- },
- "tree-kill": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
- "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
- "dev": true
- },
- "tslib": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
- "dev": true
- },
- "tsutils": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
- "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
- "dev": true,
- "requires": {
- "tslib": "^1.8.1"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "dev": true
- }
- }
- },
- "type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1"
- }
- },
- "type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true
- },
- "type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true
- },
- "typedoc": {
- "version": "0.25.2",
- "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.2.tgz",
- "integrity": "sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==",
- "dev": true,
- "requires": {
- "lunr": "^2.3.9",
- "marked": "^4.3.0",
- "minimatch": "^9.0.3",
- "shiki": "^0.14.1"
- },
- "dependencies": {
- "brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dev": true,
- "requires": {
- "balanced-match": "^1.0.0"
- }
- },
- "minimatch": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
- "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
- "dev": true,
- "requires": {
- "brace-expansion": "^2.0.1"
- }
- }
- }
- },
- "typescript": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
- "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
- "dev": true
- },
- "ufo": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz",
- "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==",
- "dev": true
- },
- "uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- },
- "vite": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz",
- "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==",
- "dev": true,
- "requires": {
- "esbuild": "^0.18.10",
- "fsevents": "~2.3.2",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
- }
- },
- "vite-node": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz",
- "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==",
- "dev": true,
- "requires": {
- "cac": "^6.7.14",
- "debug": "^4.3.4",
- "mlly": "^1.4.0",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
- }
- },
- "vitest": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz",
- "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==",
- "dev": true,
- "requires": {
- "@types/chai": "^4.3.5",
- "@types/chai-subset": "^1.3.3",
- "@types/node": "*",
- "@vitest/expect": "0.34.6",
- "@vitest/runner": "0.34.6",
- "@vitest/snapshot": "0.34.6",
- "@vitest/spy": "0.34.6",
- "@vitest/utils": "0.34.6",
- "acorn": "^8.9.0",
- "acorn-walk": "^8.2.0",
- "cac": "^6.7.14",
- "chai": "^4.3.10",
- "debug": "^4.3.4",
- "local-pkg": "^0.4.3",
- "magic-string": "^0.30.1",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "std-env": "^3.3.3",
- "strip-literal": "^1.0.1",
- "tinybench": "^2.5.0",
- "tinypool": "^0.7.0",
- "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0",
- "vite-node": "0.34.6",
- "why-is-node-running": "^2.2.2"
- }
- },
- "vscode-oniguruma": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
- "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==",
- "dev": true
- },
- "vscode-textmate": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
- "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
- "dev": true
- },
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "why-is-node-running": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
- "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
- "dev": true,
- "requires": {
- "siginfo": "^2.0.0",
- "stackback": "0.0.2"
- }
- },
- "wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true
- },
- "ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true
- },
- "strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "requires": {
- "ansi-regex": "^6.0.1"
- }
- }
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- },
- "yaml": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz",
- "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==",
- "dev": true
- },
- "yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
- "requires": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "dependencies": {
- "emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
- },
- "string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- }
- }
- }
- },
- "yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true
- },
- "yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true
- }
- }
-}
diff --git a/package.json b/package.json
index fe45dcd9..6ba4db93 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,12 @@
{
"name": "@lightningjs/renderer",
- "version": "0.9.4",
+ "version": "1.0.0-rc.3",
"description": "Lightning 3 Renderer",
"type": "module",
"main": "./dist/exports/index.js",
"exports": {
- ".": "./dist/exports/main-api.js",
- "./core": "./dist/exports/core-api.js",
- "./utils": "./dist/exports/utils.js",
- "./workers/renderer": "./dist/src/render-drivers/threadx/worker/renderer.js"
+ ".": "./dist/exports/index.js",
+ "./utils": "./dist/exports/utils.js"
},
"scripts": {
"preinstall": "node scripts/please-use-pnpm.js",
@@ -18,6 +16,7 @@
"build:docker": "docker build -t visual-regression .",
"watch": "tsc --build --watch",
"test": "vitest",
+ "coverage": "vitest run --coverage",
"test:visual": "cd visual-regression && pnpm test:visual",
"lint": "pnpm run lint:prettier && pnpm run lint:eslint",
"lint:fix": "pnpm run lint:fix:prettier && pnpm run lint:fix:eslint",
@@ -49,9 +48,10 @@
},
"homepage": "https://github.com/lightning-js/renderer#readme",
"devDependencies": {
- "@types/node": "^18.14.6",
+ "@types/node": "^20.0.0",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
+ "@vitest/coverage-v8": "^1.6.0",
"concurrently": "^8.0.1",
"eslint": "^8.35.0",
"eslint-config-prettier": "^8.7.0",
@@ -60,7 +60,8 @@
"prettier": "^2.8.4",
"typedoc": "^0.25.1",
"typescript": "^5.2.2",
- "vitest": "^0.34.2"
+ "vitest": "^1.6.0",
+ "vitest-mock-extended": "^1.3.1"
},
"dependencies": {
"@lightningjs/threadx": "^0.3.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 55e199c9..db1d3b9a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,14 +19,17 @@ importers:
version: 2.1.0
devDependencies:
'@types/node':
- specifier: ^18.14.6
- version: 18.18.6
+ specifier: ^20.0.0
+ version: 20.14.9
'@typescript-eslint/eslint-plugin':
specifier: ^5.55.0
version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/parser':
specifier: ^5.55.0
version: 5.62.0(eslint@8.52.0)(typescript@5.2.2)
+ '@vitest/coverage-v8':
+ specifier: ^1.6.0
+ version: 1.6.0(vitest@1.6.0)
concurrently:
specifier: ^8.0.1
version: 8.2.2
@@ -52,8 +55,11 @@ importers:
specifier: ^5.2.2
version: 5.2.2
vitest:
- specifier: ^0.34.2
- version: 0.34.6
+ specifier: ^1.6.0
+ version: 1.6.0(@types/node@20.14.9)
+ vitest-mock-extended:
+ specifier: ^1.3.1
+ version: 1.3.1(typescript@5.2.2)(vitest@1.6.0)
examples:
dependencies:
@@ -64,12 +70,9 @@ importers:
specifier: ^0.2.1
version: 0.2.1
devDependencies:
- '@lightningjs/vite-plugin-import-chunk-url':
- specifier: ^0.3.0
- version: 0.3.0(vite@4.5.0)
vite:
- specifier: ^4.4.9
- version: 4.5.0(@types/node@18.18.6)
+ specifier: ^5.0.0
+ version: 5.3.1(@types/node@20.14.9)
visual-regression:
dependencies:
@@ -115,6 +118,32 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /@ampproject/remapping@2.3.0:
+ resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.5
+ '@jridgewell/trace-mapping': 0.3.25
+ dev: true
+
+ /@babel/helper-string-parser@7.24.7:
+ resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-identifier@7.24.7:
+ resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/parser@7.24.7:
+ resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.24.7
+ dev: true
+
/@babel/runtime@7.23.2:
resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==}
engines: {node: '>=6.9.0'}
@@ -122,8 +151,30 @@ packages:
regenerator-runtime: 0.14.0
dev: true
- /@esbuild/android-arm64@0.18.20:
- resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
+ /@babel/types@7.24.7:
+ resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.24.7
+ '@babel/helper-validator-identifier': 7.24.7
+ to-fast-properties: 2.0.0
+ dev: true
+
+ /@bcoe/v8-coverage@0.2.3:
+ resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
+ dev: true
+
+ /@esbuild/aix-ppc64@0.21.5:
+ resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64@0.21.5:
+ resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
@@ -131,8 +182,8 @@ packages:
dev: true
optional: true
- /@esbuild/android-arm@0.18.20:
- resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
+ /@esbuild/android-arm@0.21.5:
+ resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
@@ -140,8 +191,8 @@ packages:
dev: true
optional: true
- /@esbuild/android-x64@0.18.20:
- resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
+ /@esbuild/android-x64@0.21.5:
+ resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
@@ -149,8 +200,8 @@ packages:
dev: true
optional: true
- /@esbuild/darwin-arm64@0.18.20:
- resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
+ /@esbuild/darwin-arm64@0.21.5:
+ resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
@@ -158,8 +209,8 @@ packages:
dev: true
optional: true
- /@esbuild/darwin-x64@0.18.20:
- resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
+ /@esbuild/darwin-x64@0.21.5:
+ resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
@@ -167,8 +218,8 @@ packages:
dev: true
optional: true
- /@esbuild/freebsd-arm64@0.18.20:
- resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
+ /@esbuild/freebsd-arm64@0.21.5:
+ resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
@@ -176,8 +227,8 @@ packages:
dev: true
optional: true
- /@esbuild/freebsd-x64@0.18.20:
- resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
+ /@esbuild/freebsd-x64@0.21.5:
+ resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
@@ -185,8 +236,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-arm64@0.18.20:
- resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
+ /@esbuild/linux-arm64@0.21.5:
+ resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
@@ -194,8 +245,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-arm@0.18.20:
- resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
+ /@esbuild/linux-arm@0.21.5:
+ resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
@@ -203,8 +254,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-ia32@0.18.20:
- resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
+ /@esbuild/linux-ia32@0.21.5:
+ resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
@@ -212,8 +263,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-loong64@0.18.20:
- resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
+ /@esbuild/linux-loong64@0.21.5:
+ resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
@@ -221,8 +272,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-mips64el@0.18.20:
- resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
+ /@esbuild/linux-mips64el@0.21.5:
+ resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
@@ -230,8 +281,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-ppc64@0.18.20:
- resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
+ /@esbuild/linux-ppc64@0.21.5:
+ resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
@@ -239,8 +290,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-riscv64@0.18.20:
- resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
+ /@esbuild/linux-riscv64@0.21.5:
+ resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
@@ -248,8 +299,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-s390x@0.18.20:
- resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
+ /@esbuild/linux-s390x@0.21.5:
+ resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
@@ -257,8 +308,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-x64@0.18.20:
- resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
+ /@esbuild/linux-x64@0.21.5:
+ resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
@@ -266,8 +317,8 @@ packages:
dev: true
optional: true
- /@esbuild/netbsd-x64@0.18.20:
- resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
+ /@esbuild/netbsd-x64@0.21.5:
+ resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
@@ -275,8 +326,8 @@ packages:
dev: true
optional: true
- /@esbuild/openbsd-x64@0.18.20:
- resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
+ /@esbuild/openbsd-x64@0.21.5:
+ resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
@@ -284,8 +335,8 @@ packages:
dev: true
optional: true
- /@esbuild/sunos-x64@0.18.20:
- resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
+ /@esbuild/sunos-x64@0.21.5:
+ resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
@@ -293,8 +344,8 @@ packages:
dev: true
optional: true
- /@esbuild/win32-arm64@0.18.20:
- resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
+ /@esbuild/win32-arm64@0.21.5:
+ resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
@@ -302,8 +353,8 @@ packages:
dev: true
optional: true
- /@esbuild/win32-ia32@0.18.20:
- resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
+ /@esbuild/win32-ia32@0.21.5:
+ resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
@@ -311,8 +362,8 @@ packages:
dev: true
optional: true
- /@esbuild/win32-x64@0.18.20:
- resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
+ /@esbuild/win32-x64@0.21.5:
+ resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
@@ -377,6 +428,11 @@ packages:
resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==}
dev: true
+ /@istanbuljs/schema@0.1.3:
+ resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
+ engines: {node: '>=8'}
+ dev: true
+
/@jest/schemas@29.6.3:
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -384,22 +440,40 @@ packages:
'@sinclair/typebox': 0.27.8
dev: true
+ /@jridgewell/gen-mapping@0.3.5:
+ resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.2.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.25
+ dev: true
+
+ /@jridgewell/resolve-uri@3.1.2:
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/set-array@1.2.1:
+ resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
/@jridgewell/sourcemap-codec@1.4.15:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
+ /@jridgewell/trace-mapping@0.3.25:
+ resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
/@lightningjs/threadx@0.3.5:
resolution: {integrity: sha512-aUIUfP/d3S0Vg/Ror7CLbqQR6qu5AAdGRnQ5RQuSQz4t9X2p8TomKD7ShRxI1/FnRR7om2MwKIe1Dix/Axdgpg==}
dev: false
- /@lightningjs/vite-plugin-import-chunk-url@0.3.0(vite@4.5.0):
- resolution: {integrity: sha512-cozdB9gcPrnITWTymo525Vb+98EfsBOBQnrbzXI6rOFveshxc754eco0ffnuqyFUkN8pds+DwJrJ5saJDmJz/g==}
- peerDependencies:
- vite: ^4.4.9
- dependencies:
- vite: 4.5.0(@types/node@18.18.6)
- dev: true
-
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -425,6 +499,134 @@ packages:
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
dev: false
+ /@rollup/rollup-android-arm-eabi@4.18.0:
+ resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-android-arm64@4.18.0:
+ resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-arm64@4.18.0:
+ resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-x64@4.18.0:
+ resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-gnueabihf@4.18.0:
+ resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-musleabihf@4.18.0:
+ resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-gnu@4.18.0:
+ resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-musl@4.18.0:
+ resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-powerpc64le-gnu@4.18.0:
+ resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-riscv64-gnu@4.18.0:
+ resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-s390x-gnu@4.18.0:
+ resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-gnu@4.18.0:
+ resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-musl@4.18.0:
+ resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-arm64-msvc@4.18.0:
+ resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-ia32-msvc@4.18.0:
+ resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-x64-msvc@4.18.0:
+ resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@sinclair/typebox@0.27.8:
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
dev: true
@@ -1670,14 +1872,8 @@ packages:
'@stdlib/utils-global': 0.2.1
dev: false
- /@types/chai-subset@1.3.4:
- resolution: {integrity: sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==}
- dependencies:
- '@types/chai': 4.3.9
- dev: true
-
- /@types/chai@4.3.9:
- resolution: {integrity: sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==}
+ /@types/estree@1.0.5:
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
dev: true
/@types/fs-extra@11.0.4:
@@ -1701,6 +1897,12 @@ packages:
resolution: {integrity: sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==}
dev: true
+ /@types/node@20.14.9:
+ resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==}
+ dependencies:
+ undici-types: 5.26.5
+ dev: true
+
/@types/semver@7.5.4:
resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==}
dev: true
@@ -1853,40 +2055,64 @@ packages:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: true
- /@vitest/expect@0.34.6:
- resolution: {integrity: sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==}
+ /@vitest/coverage-v8@1.6.0(vitest@1.6.0):
+ resolution: {integrity: sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==}
+ peerDependencies:
+ vitest: 1.6.0
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@bcoe/v8-coverage': 0.2.3
+ debug: 4.3.4
+ istanbul-lib-coverage: 3.2.2
+ istanbul-lib-report: 3.0.1
+ istanbul-lib-source-maps: 5.0.4
+ istanbul-reports: 3.1.7
+ magic-string: 0.30.5
+ magicast: 0.3.4
+ picocolors: 1.0.0
+ std-env: 3.7.0
+ strip-literal: 2.1.0
+ test-exclude: 6.0.0
+ vitest: 1.6.0(@types/node@20.14.9)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@vitest/expect@1.6.0:
+ resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==}
dependencies:
- '@vitest/spy': 0.34.6
- '@vitest/utils': 0.34.6
+ '@vitest/spy': 1.6.0
+ '@vitest/utils': 1.6.0
chai: 4.3.10
dev: true
- /@vitest/runner@0.34.6:
- resolution: {integrity: sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==}
+ /@vitest/runner@1.6.0:
+ resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==}
dependencies:
- '@vitest/utils': 0.34.6
- p-limit: 4.0.0
+ '@vitest/utils': 1.6.0
+ p-limit: 5.0.0
pathe: 1.1.1
dev: true
- /@vitest/snapshot@0.34.6:
- resolution: {integrity: sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==}
+ /@vitest/snapshot@1.6.0:
+ resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==}
dependencies:
magic-string: 0.30.5
pathe: 1.1.1
pretty-format: 29.7.0
dev: true
- /@vitest/spy@0.34.6:
- resolution: {integrity: sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==}
+ /@vitest/spy@1.6.0:
+ resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==}
dependencies:
tinyspy: 2.2.0
dev: true
- /@vitest/utils@0.34.6:
- resolution: {integrity: sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==}
+ /@vitest/utils@1.6.0:
+ resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==}
dependencies:
diff-sequences: 29.6.3
+ estree-walker: 3.0.3
loupe: 2.3.7
pretty-format: 29.7.0
dev: true
@@ -1899,9 +2125,11 @@ packages:
acorn: 8.10.0
dev: true
- /acorn-walk@8.2.0:
- resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
+ /acorn-walk@8.3.3:
+ resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==}
engines: {node: '>=0.4.0'}
+ dependencies:
+ acorn: 8.12.0
dev: true
/acorn@8.10.0:
@@ -1910,6 +2138,12 @@ packages:
hasBin: true
dev: true
+ /acorn@8.12.0:
+ resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
/ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
dependencies:
@@ -2178,34 +2412,35 @@ packages:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
dev: true
- /esbuild@0.18.20:
- resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
+ /esbuild@0.21.5:
+ resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
optionalDependencies:
- '@esbuild/android-arm': 0.18.20
- '@esbuild/android-arm64': 0.18.20
- '@esbuild/android-x64': 0.18.20
- '@esbuild/darwin-arm64': 0.18.20
- '@esbuild/darwin-x64': 0.18.20
- '@esbuild/freebsd-arm64': 0.18.20
- '@esbuild/freebsd-x64': 0.18.20
- '@esbuild/linux-arm': 0.18.20
- '@esbuild/linux-arm64': 0.18.20
- '@esbuild/linux-ia32': 0.18.20
- '@esbuild/linux-loong64': 0.18.20
- '@esbuild/linux-mips64el': 0.18.20
- '@esbuild/linux-ppc64': 0.18.20
- '@esbuild/linux-riscv64': 0.18.20
- '@esbuild/linux-s390x': 0.18.20
- '@esbuild/linux-x64': 0.18.20
- '@esbuild/netbsd-x64': 0.18.20
- '@esbuild/openbsd-x64': 0.18.20
- '@esbuild/sunos-x64': 0.18.20
- '@esbuild/win32-arm64': 0.18.20
- '@esbuild/win32-ia32': 0.18.20
- '@esbuild/win32-x64': 0.18.20
+ '@esbuild/aix-ppc64': 0.21.5
+ '@esbuild/android-arm': 0.21.5
+ '@esbuild/android-arm64': 0.21.5
+ '@esbuild/android-x64': 0.21.5
+ '@esbuild/darwin-arm64': 0.21.5
+ '@esbuild/darwin-x64': 0.21.5
+ '@esbuild/freebsd-arm64': 0.21.5
+ '@esbuild/freebsd-x64': 0.21.5
+ '@esbuild/linux-arm': 0.21.5
+ '@esbuild/linux-arm64': 0.21.5
+ '@esbuild/linux-ia32': 0.21.5
+ '@esbuild/linux-loong64': 0.21.5
+ '@esbuild/linux-mips64el': 0.21.5
+ '@esbuild/linux-ppc64': 0.21.5
+ '@esbuild/linux-riscv64': 0.21.5
+ '@esbuild/linux-s390x': 0.21.5
+ '@esbuild/linux-x64': 0.21.5
+ '@esbuild/netbsd-x64': 0.21.5
+ '@esbuild/openbsd-x64': 0.21.5
+ '@esbuild/sunos-x64': 0.21.5
+ '@esbuild/win32-arm64': 0.21.5
+ '@esbuild/win32-ia32': 0.21.5
+ '@esbuild/win32-x64': 0.21.5
dev: true
/escalade@3.1.1:
@@ -2327,6 +2562,12 @@ packages:
engines: {node: '>=4.0'}
dev: true
+ /estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+ dependencies:
+ '@types/estree': 1.0.5
+ dev: true
+
/esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
@@ -2364,7 +2605,6 @@ packages:
onetime: 6.0.0
signal-exit: 4.1.0
strip-final-newline: 3.0.0
- dev: false
/fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -2479,7 +2719,6 @@ packages:
/get-stream@8.0.1:
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
engines: {node: '>=16'}
- dev: false
/glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
@@ -2545,6 +2784,10 @@ packages:
function-bind: 1.1.2
dev: false
+ /html-escaper@2.0.2:
+ resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ dev: true
+
/human-signals@4.3.1:
resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==}
engines: {node: '>=14.18.0'}
@@ -2553,7 +2796,6 @@ packages:
/human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
- dev: false
/husky@8.0.3:
resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==}
@@ -2590,8 +2832,9 @@ packages:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
- /is-core-module@2.13.1:
- resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+ /is-core-module@2.14.0:
+ resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==}
+ engines: {node: '>= 0.4'}
dependencies:
hasown: 2.0.2
dev: false
@@ -2634,6 +2877,43 @@ packages:
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ /istanbul-lib-coverage@3.2.2:
+ resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /istanbul-lib-report@3.0.1:
+ resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+ engines: {node: '>=10'}
+ dependencies:
+ istanbul-lib-coverage: 3.2.2
+ make-dir: 4.0.0
+ supports-color: 7.2.0
+ dev: true
+
+ /istanbul-lib-source-maps@5.0.4:
+ resolution: {integrity: sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==}
+ engines: {node: '>=10'}
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.25
+ debug: 4.3.4
+ istanbul-lib-coverage: 3.2.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /istanbul-reports@3.1.7:
+ resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
+ engines: {node: '>=8'}
+ dependencies:
+ html-escaper: 2.0.2
+ istanbul-lib-report: 3.0.1
+ dev: true
+
+ /js-tokens@9.0.0:
+ resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==}
+ dev: true
+
/js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
@@ -2721,9 +3001,12 @@ packages:
wrap-ansi: 8.1.0
dev: true
- /local-pkg@0.4.3:
- resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
+ /local-pkg@0.5.0:
+ resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
engines: {node: '>=14'}
+ dependencies:
+ mlly: 1.4.2
+ pkg-types: 1.0.3
dev: true
/locate-path@6.0.0:
@@ -2776,6 +3059,21 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
+ /magicast@0.3.4:
+ resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==}
+ dependencies:
+ '@babel/parser': 7.24.7
+ '@babel/types': 7.24.7
+ source-map-js: 1.2.0
+ dev: true
+
+ /make-dir@4.0.0:
+ resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+ engines: {node: '>=10'}
+ dependencies:
+ semver: 7.5.4
+ dev: true
+
/marked@4.3.0:
resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==}
engines: {node: '>= 12'}
@@ -2841,8 +3139,8 @@ packages:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
- /nanoid@3.3.6:
- resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
+ /nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: true
@@ -2899,9 +3197,9 @@ packages:
yocto-queue: 0.1.0
dev: true
- /p-limit@4.0.0:
- resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ /p-limit@5.0.0:
+ resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==}
+ engines: {node: '>=18'}
dependencies:
yocto-queue: 1.0.0
dev: true
@@ -2998,13 +3296,13 @@ packages:
fsevents: 2.3.2
dev: true
- /postcss@8.4.31:
- resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
+ /postcss@8.4.38:
+ resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
- nanoid: 3.3.6
+ nanoid: 3.3.7
picocolors: 1.0.0
- source-map-js: 1.0.2
+ source-map-js: 1.2.0
dev: true
/prelude-ls@1.2.1:
@@ -3057,7 +3355,7 @@ packages:
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
hasBin: true
dependencies:
- is-core-module: 2.13.1
+ is-core-module: 2.14.0
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
dev: false
@@ -3086,11 +3384,29 @@ packages:
glob: 7.2.3
dev: true
- /rollup@3.29.4:
- resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
- engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ /rollup@4.18.0:
+ resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ dependencies:
+ '@types/estree': 1.0.5
optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.18.0
+ '@rollup/rollup-android-arm64': 4.18.0
+ '@rollup/rollup-darwin-arm64': 4.18.0
+ '@rollup/rollup-darwin-x64': 4.18.0
+ '@rollup/rollup-linux-arm-gnueabihf': 4.18.0
+ '@rollup/rollup-linux-arm-musleabihf': 4.18.0
+ '@rollup/rollup-linux-arm64-gnu': 4.18.0
+ '@rollup/rollup-linux-arm64-musl': 4.18.0
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0
+ '@rollup/rollup-linux-riscv64-gnu': 4.18.0
+ '@rollup/rollup-linux-s390x-gnu': 4.18.0
+ '@rollup/rollup-linux-x64-gnu': 4.18.0
+ '@rollup/rollup-linux-x64-musl': 4.18.0
+ '@rollup/rollup-win32-arm64-msvc': 4.18.0
+ '@rollup/rollup-win32-ia32-msvc': 4.18.0
+ '@rollup/rollup-win32-x64-msvc': 4.18.0
fsevents: 2.3.3
dev: true
@@ -3148,7 +3464,6 @@ packages:
/signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
- dev: false
/slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
@@ -3163,8 +3478,8 @@ packages:
is-fullwidth-code-point: 4.0.0
dev: true
- /source-map-js@1.0.2:
- resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ /source-map-js@1.2.0:
+ resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
engines: {node: '>=0.10.0'}
dev: true
@@ -3176,8 +3491,8 @@ packages:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
dev: true
- /std-env@3.4.3:
- resolution: {integrity: sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==}
+ /std-env@3.7.0:
+ resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
dev: true
/string-argv@0.3.2:
@@ -3224,10 +3539,10 @@ packages:
engines: {node: '>=8'}
dev: true
- /strip-literal@1.3.0:
- resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==}
+ /strip-literal@2.1.0:
+ resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
dependencies:
- acorn: 8.10.0
+ js-tokens: 9.0.0
dev: true
/supports-color@7.2.0:
@@ -3249,6 +3564,15 @@ packages:
engines: {node: '>= 0.4'}
dev: false
+ /test-exclude@6.0.0:
+ resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
+ engines: {node: '>=8'}
+ dependencies:
+ '@istanbuljs/schema': 0.1.3
+ glob: 7.2.3
+ minimatch: 3.1.2
+ dev: true
+
/text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: true
@@ -3257,8 +3581,8 @@ packages:
resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==}
dev: true
- /tinypool@0.7.0:
- resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==}
+ /tinypool@0.8.4:
+ resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==}
engines: {node: '>=14.0.0'}
dev: true
@@ -3267,6 +3591,11 @@ packages:
engines: {node: '>=14.0.0'}
dev: true
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: true
+
/to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
@@ -3279,6 +3608,17 @@ packages:
hasBin: true
dev: true
+ /ts-essentials@9.4.2(typescript@5.2.2):
+ resolution: {integrity: sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==}
+ peerDependencies:
+ typescript: '>=4.1.0'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ typescript: 5.2.2
+ dev: true
+
/tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
dev: true
@@ -3343,6 +3683,10 @@ packages:
resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==}
dev: true
+ /undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ dev: true
+
/universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
@@ -3360,17 +3704,16 @@ packages:
punycode: 2.3.0
dev: true
- /vite-node@0.34.6(@types/node@18.18.6):
- resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==}
- engines: {node: '>=v14.18.0'}
+ /vite-node@1.6.0(@types/node@20.14.9):
+ resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==}
+ engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
dependencies:
cac: 6.7.14
debug: 4.3.4
- mlly: 1.4.2
pathe: 1.1.1
picocolors: 1.0.0
- vite: 4.5.0(@types/node@18.18.6)
+ vite: 5.3.1(@types/node@20.14.9)
transitivePeerDependencies:
- '@types/node'
- less
@@ -3382,12 +3725,12 @@ packages:
- terser
dev: true
- /vite@4.5.0(@types/node@18.18.6):
- resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
- engines: {node: ^14.18.0 || >=16.0.0}
+ /vite@5.3.1(@types/node@20.14.9):
+ resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
- '@types/node': '>= 14'
+ '@types/node': ^18.0.0 || >=20.0.0
less: '*'
lightningcss: ^1.21.0
sass: '*'
@@ -3410,30 +3753,41 @@ packages:
terser:
optional: true
dependencies:
- '@types/node': 18.18.6
- esbuild: 0.18.20
- postcss: 8.4.31
- rollup: 3.29.4
+ '@types/node': 20.14.9
+ esbuild: 0.21.5
+ postcss: 8.4.38
+ rollup: 4.18.0
optionalDependencies:
fsevents: 2.3.3
dev: true
- /vitest@0.34.6:
- resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==}
- engines: {node: '>=v14.18.0'}
+ /vitest-mock-extended@1.3.1(typescript@5.2.2)(vitest@1.6.0):
+ resolution: {integrity: sha512-OpghYjh4BDuQ/Mzs3lFMQ1QRk9D8/2O9T47MLUA5eLn7K4RWIy+MfIivYOWEyxjTENjsBnzgMihDjyNalN/K0Q==}
+ peerDependencies:
+ typescript: 3.x || 4.x || 5.x
+ vitest: '>=0.31.1'
+ dependencies:
+ ts-essentials: 9.4.2(typescript@5.2.2)
+ typescript: 5.2.2
+ vitest: 1.6.0(@types/node@20.14.9)
+ dev: true
+
+ /vitest@1.6.0(@types/node@20.14.9):
+ resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
- '@vitest/browser': '*'
- '@vitest/ui': '*'
+ '@types/node': ^18.0.0 || >=20.0.0
+ '@vitest/browser': 1.6.0
+ '@vitest/ui': 1.6.0
happy-dom: '*'
jsdom: '*'
- playwright: '*'
- safaridriver: '*'
- webdriverio: '*'
peerDependenciesMeta:
'@edge-runtime/vm':
optional: true
+ '@types/node':
+ optional: true
'@vitest/browser':
optional: true
'@vitest/ui':
@@ -3442,36 +3796,27 @@ packages:
optional: true
jsdom:
optional: true
- playwright:
- optional: true
- safaridriver:
- optional: true
- webdriverio:
- optional: true
dependencies:
- '@types/chai': 4.3.9
- '@types/chai-subset': 1.3.4
- '@types/node': 18.18.6
- '@vitest/expect': 0.34.6
- '@vitest/runner': 0.34.6
- '@vitest/snapshot': 0.34.6
- '@vitest/spy': 0.34.6
- '@vitest/utils': 0.34.6
- acorn: 8.10.0
- acorn-walk: 8.2.0
- cac: 6.7.14
+ '@types/node': 20.14.9
+ '@vitest/expect': 1.6.0
+ '@vitest/runner': 1.6.0
+ '@vitest/snapshot': 1.6.0
+ '@vitest/spy': 1.6.0
+ '@vitest/utils': 1.6.0
+ acorn-walk: 8.3.3
chai: 4.3.10
debug: 4.3.4
- local-pkg: 0.4.3
+ execa: 8.0.1
+ local-pkg: 0.5.0
magic-string: 0.30.5
pathe: 1.1.1
picocolors: 1.0.0
- std-env: 3.4.3
- strip-literal: 1.3.0
+ std-env: 3.7.0
+ strip-literal: 2.1.0
tinybench: 2.5.1
- tinypool: 0.7.0
- vite: 4.5.0(@types/node@18.18.6)
- vite-node: 0.34.6(@types/node@18.18.6)
+ tinypool: 0.8.4
+ vite: 5.3.1(@types/node@20.14.9)
+ vite-node: 1.6.0(@types/node@20.14.9)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
diff --git a/src/core/CoreExtension.ts b/src/core/CoreExtension.ts
deleted file mode 100644
index 00fb9ff2..00000000
--- a/src/core/CoreExtension.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * If not stated otherwise in this file or this component's LICENSE file the
- * following copyright and licenses apply:
- *
- * Copyright 2023 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import type { Stage } from './Stage.js';
-
-/**
- * Base class for Core extensions.
- *
- * @remarks
- * Core extensions are used to extend the Core Renderer with custom code such as
- * custom fonts, custom shaders, custom textures, custom animation functions,
- * and more.
- */
-export abstract class CoreExtension {
- abstract run(stage: Stage): Promise;
-}
diff --git a/src/core/CoreNode.test.ts b/src/core/CoreNode.test.ts
new file mode 100644
index 00000000..fc945c34
--- /dev/null
+++ b/src/core/CoreNode.test.ts
@@ -0,0 +1,93 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { describe, expect, it } from 'vitest';
+import { CoreNode, type CoreNodeProps, UpdateType } from './CoreNode.js';
+import { Stage } from './Stage.js';
+import { mock } from 'vitest-mock-extended';
+import { type TextureOptions } from './CoreTextureManager.js';
+import { type BaseShaderController } from '../main-api/ShaderController';
+
+describe('set color()', () => {
+ const defaultProps: CoreNodeProps = {
+ alpha: 0,
+ autosize: false,
+ clipping: false,
+ color: 0,
+ colorBl: 0,
+ colorBottom: 0,
+ colorBr: 0,
+ colorLeft: 0,
+ colorRight: 0,
+ colorTl: 0,
+ colorTop: 0,
+ colorTr: 0,
+ height: 0,
+ mount: 0,
+ mountX: 0,
+ mountY: 0,
+ parent: null,
+ pivot: 0,
+ pivotX: 0,
+ pivotY: 0,
+ rotation: 0,
+ rtt: false,
+ scale: 0,
+ scaleX: 0,
+ scaleY: 0,
+ shader: mock(),
+ src: '',
+ texture: null,
+ textureOptions: {} as TextureOptions,
+ width: 0,
+ x: 0,
+ y: 0,
+ zIndex: 0,
+ zIndexLocked: 0,
+ };
+
+ it('should set all color subcomponents.', () => {
+ const node = new CoreNode(mock(), defaultProps);
+ node.colorBl = 0x99aabbff;
+ node.colorBr = 0xaabbccff;
+ node.colorTl = 0xbbcceeff;
+ node.colorTr = 0xcceeffff;
+
+ node.color = 0xffffffff;
+
+ expect(node.color).toBe(0xffffffff);
+ expect(node.colorBl).toBe(0xffffffff);
+ expect(node.colorBr).toBe(0xffffffff);
+ expect(node.colorTl).toBe(0xffffffff);
+ expect(node.colorTr).toBe(0xffffffff);
+ expect(node.colorLeft).toBe(0xffffffff);
+ expect(node.colorRight).toBe(0xffffffff);
+ expect(node.colorTop).toBe(0xffffffff);
+ expect(node.colorBottom).toBe(0xffffffff);
+ });
+
+ it('should set update type.', () => {
+ const node = new CoreNode(mock(), defaultProps);
+ node.updateType = 0;
+
+ node.color = 0xffffffff;
+
+ expect(node.updateType).toBe(UpdateType.PremultipliedColors);
+ });
+});
diff --git a/src/core/CoreNode.ts b/src/core/CoreNode.ts
index a1650c79..79db1024 100644
--- a/src/core/CoreNode.ts
+++ b/src/core/CoreNode.ts
@@ -19,17 +19,11 @@
import {
assertTruthy,
+ getNewId,
mergeColorAlphaPremultiplied,
- getImageAspectRatio,
} from '../utils.js';
-import type { ShaderMap } from './CoreShaderManager.js';
-import type {
- ExtractProps,
- TextureMap,
- TextureOptions,
-} from './CoreTextureManager.js';
+import type { TextureOptions } from './CoreTextureManager.js';
import type { CoreRenderer } from './renderers/CoreRenderer.js';
-import type { CoreShader } from './renderers/CoreShader.js';
import type { Stage } from './Stage.js';
import type {
Texture,
@@ -37,7 +31,6 @@ import type {
TextureFreedEventHandler,
TextureLoadedEventHandler,
} from './textures/Texture.js';
-import { RenderTexture } from './textures/RenderTexture.js';
import type {
Dimensions,
NodeTextureFailedPayload,
@@ -55,6 +48,11 @@ import {
} from './lib/utils.js';
import { Matrix3d } from './lib/Matrix3d.js';
import { RenderCoords } from './lib/RenderCoords.js';
+import type { AnimationSettings } from './animations/CoreAnimation.js';
+import type { IAnimationController } from '../common/IAnimationController.js';
+import { CoreAnimation } from './animations/CoreAnimation.js';
+import { CoreAnimationController } from './animations/CoreAnimationController.js';
+import type { BaseShaderController } from '../main-api/ShaderController.js';
export enum CoreNodeRenderState {
Init = 0,
@@ -69,50 +67,6 @@ CoreNodeRenderStateMap.set(CoreNodeRenderState.OutOfBounds, 'outOfBounds');
CoreNodeRenderStateMap.set(CoreNodeRenderState.InBounds, 'inBounds');
CoreNodeRenderStateMap.set(CoreNodeRenderState.InViewport, 'inViewport');
-export interface CoreNodeProps {
- id: number;
- // External facing properties whose defaults are determined by
- // RendererMain's resolveNodeDefaults() method
- x: number;
- y: number;
- width: number;
- height: number;
- alpha: number;
- autosize: boolean;
- clipping: boolean;
- color: number;
- colorTop: number;
- colorBottom: number;
- colorLeft: number;
- colorRight: number;
- colorTl: number;
- colorTr: number;
- colorBl: number;
- colorBr: number;
- parent: CoreNode | null;
- zIndex: number;
- texture: Texture | null;
- textureOptions: TextureOptions | null;
- shader: CoreShader | null;
- shaderProps: Record | null;
- zIndexLocked: number;
- scaleX: number;
- scaleY: number;
- mount: number;
- mountX: number;
- mountY: number;
- pivot: number;
- pivotX: number;
- pivotY: number;
- rotation: number;
- rtt: boolean;
-}
-
-type ICoreNode = Omit<
- CoreNodeProps,
- 'texture' | 'textureOptions' | 'shader' | 'shaderProps'
->;
-
export enum UpdateType {
/**
* Child updates
@@ -235,9 +189,462 @@ export enum UpdateType {
All = 8191,
}
-export class CoreNode extends EventEmitter implements ICoreNode {
+/**
+ * A custom data map which can be stored on an CoreNode
+ *
+ * @remarks
+ * This is a map of key-value pairs that can be stored on an INode. It is used
+ * to store custom data that can be used by the application.
+ * The data stored can only be of type string, number or boolean.
+ */
+export type CustomDataMap = {
+ [key: string]: string | number | boolean | undefined;
+};
+
+/**
+ * Writable properties of a Node.
+ */
+export interface CoreNodeProps {
+ /**
+ * The x coordinate of the Node's Mount Point.
+ *
+ * @remarks
+ * See {@link mountX} and {@link mountY} for more information about setting
+ * the Mount Point.
+ *
+ * @default `0`
+ */
+ x: number;
+ /**
+ * The y coordinate of the Node's Mount Point.
+ *
+ * @remarks
+ * See {@link mountX} and {@link mountY} for more information about setting
+ * the Mount Point.
+ *
+ * @default `0`
+ */
+ y: number;
+ /**
+ * The width of the Node.
+ *
+ * @default `0`
+ */
+ width: number;
+ /**
+ * The height of the Node.
+ *
+ * @default `0`
+ */
+ height: number;
+ /**
+ * The alpha opacity of the Node.
+ *
+ * @remarks
+ * The alpha value is a number between 0 and 1, where 0 is fully transparent
+ * and 1 is fully opaque.
+ *
+ * @default `1`
+ */
+ alpha: number;
+ /**
+ * Autosize mode
+ *
+ * @remarks
+ * When enabled, when a texture is loaded into the Node, the Node will
+ * automatically resize to the dimensions of the texture.
+ *
+ * Text Nodes are always autosized based on their text content regardless
+ * of this mode setting.
+ *
+ * @default `false`
+ */
+ autosize: boolean;
+ /**
+ * Clipping Mode
+ *
+ * @remarks
+ * Enable Clipping Mode when you want to prevent the drawing of a Node and
+ * its descendants from overflowing outside of the Node's x/y/width/height
+ * bounds.
+ *
+ * For WebGL, clipping is implemented using the high-performance WebGL
+ * operation scissor. As a consequence, clipping does not work for
+ * non-rectangular areas. So, if the element is rotated
+ * (by itself or by any of its ancestors), clipping will not work as intended.
+ *
+ * TODO: Add support for non-rectangular clipping either automatically or
+ * via Render-To-Texture.
+ *
+ * @default `false`
+ */
+ clipping: boolean;
+ /**
+ * The color of the Node.
+ *
+ * @remarks
+ * The color value is a number in the format 0xRRGGBBAA, where RR is the red
+ * component, GG is the green component, BB is the blue component, and AA is
+ * the alpha component.
+ *
+ * Gradient colors may be set by setting the different color sub-properties:
+ * {@link colorTop}, {@link colorBottom}, {@link colorLeft}, {@link colorRight},
+ * {@link colorTl}, {@link colorTr}, {@link colorBr}, {@link colorBl} accordingly.
+ *
+ * @default `0xffffffff` (opaque white)
+ */
+ color: number;
+ /**
+ * The color of the top edge of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorTop: number;
+ /**
+ * The color of the bottom edge of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorBottom: number;
+ /**
+ * The color of the left edge of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorLeft: number;
+ /**
+ * The color of the right edge of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorRight: number;
+ /**
+ * The color of the top-left corner of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorTl: number;
+ /**
+ * The color of the top-right corner of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorTr: number;
+ /**
+ * The color of the bottom-right corner of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorBr: number;
+ /**
+ * The color of the bottom-left corner of the Node for gradient rendering.
+ *
+ * @remarks
+ * See {@link color} for more information about color values and gradient
+ * rendering.
+ */
+ colorBl: number;
+ /**
+ * The Node's parent Node.
+ *
+ * @remarks
+ * The value `null` indicates that the Node has no parent. This may either be
+ * because the Node is the root Node of the scene graph, or because the Node
+ * has been removed from the scene graph.
+ *
+ * In order to make sure that a Node can be rendered on the screen, it must
+ * be added to the scene graph by setting it's parent property to a Node that
+ * is already in the scene graph such as the root Node.
+ *
+ * @default `null`
+ */
+ parent: CoreNode | null;
+ /**
+ * The Node's z-index.
+ *
+ * @remarks
+ * TBD
+ */
+ zIndex: number;
+ /**
+ * The Node's Texture.
+ *
+ * @remarks
+ * The `texture` defines a rasterized image that is contained within the
+ * {@link width} and {@link height} dimensions of the Node. If null, the
+ * Node will use an opaque white {@link ColorTexture} when being drawn, which
+ * essentially enables colors (including gradients) to be drawn.
+ *
+ * If set, by default, the texture will be drawn, as is, stretched to the
+ * dimensions of the Node. This behavior can be modified by setting the TBD
+ * and TBD properties.
+ *
+ * To create a Texture in order to set it on this property, call
+ * {@link RendererMain.createTexture}.
+ *
+ * If the {@link src} is set on a Node, the Node will use the
+ * {@link ImageTexture} by default and the Node will simply load the image at
+ * the specified URL.
+ *
+ * Note: If this is a Text Node, the Texture will be managed by the Node's
+ * {@link TextRenderer} and should not be set explicitly.
+ */
+ texture: Texture | null;
+
+ /**
+ * Options to associate with the Node's Texture
+ */
+ textureOptions: TextureOptions;
+
+ /**
+ * The Node's shader
+ *
+ * @remarks
+ * The `shader` defines a {@link Shader} used to draw the Node. By default,
+ * the Default Shader is used which simply draws the defined {@link texture}
+ * or {@link color}(s) within the Node without any special effects.
+ *
+ * To create a Shader in order to set it on this property, call
+ * {@link RendererMain.createShader}.
+ *
+ * Note: If this is a Text Node, the Shader will be managed by the Node's
+ * {@link TextRenderer} and should not be set explicitly.
+ */
+ shader: BaseShaderController;
+ /**
+ * Image URL
+ *
+ * @remarks
+ * When set, the Node's {@link texture} is automatically set to an
+ * {@link ImageTexture} using the source image URL provided (with all other
+ * settings being defaults)
+ */
+ src: string | null;
+ zIndexLocked: number;
+ /**
+ * Scale to render the Node at
+ *
+ * @remarks
+ * The scale value multiplies the provided {@link width} and {@link height}
+ * of the Node around the Node's Pivot Point (defined by the {@link pivot}
+ * props).
+ *
+ * Behind the scenes, setting this property sets both the {@link scaleX} and
+ * {@link scaleY} props to the same value.
+ *
+ * NOTE: When the scaleX and scaleY props are explicitly set to different values,
+ * this property returns `null`. Setting `null` on this property will have no
+ * effect.
+ *
+ * @default 1.0
+ */
+ scale: number | null;
+ /**
+ * Scale to render the Node at (X-Axis)
+ *
+ * @remarks
+ * The scaleX value multiplies the provided {@link width} of the Node around
+ * the Node's Pivot Point (defined by the {@link pivot} props).
+ *
+ * @default 1.0
+ */
+ scaleX: number;
+ /**
+ * Scale to render the Node at (Y-Axis)
+ *
+ * @remarks
+ * The scaleY value multiplies the provided {@link height} of the Node around
+ * the Node's Pivot Point (defined by the {@link pivot} props).
+ *
+ * @default 1.0
+ */
+ scaleY: number;
+ /**
+ * Combined position of the Node's Mount Point
+ *
+ * @remarks
+ * The value can be any number between `0.0` and `1.0`:
+ * - `0.0` defines the Mount Point at the top-left corner of the Node.
+ * - `0.5` defines it at the center of the Node.
+ * - `1.0` defines it at the bottom-right corner of the node.
+ *
+ * Use the {@link mountX} and {@link mountY} props seperately for more control
+ * of the Mount Point.
+ *
+ * When assigned, the same value is also passed to both the {@link mountX} and
+ * {@link mountY} props.
+ *
+ * @default 0 (top-left)
+ */
+ mount: number;
+ /**
+ * X position of the Node's Mount Point
+ *
+ * @remarks
+ * The value can be any number between `0.0` and `1.0`:
+ * - `0.0` defines the Mount Point's X position as the left-most edge of the
+ * Node
+ * - `0.5` defines it as the horizontal center of the Node
+ * - `1.0` defines it as the right-most edge of the Node.
+ *
+ * The combination of {@link mountX} and {@link mountY} define the Mount Point
+ *
+ * @default 0 (left-most edge)
+ */
+ mountX: number;
+ /**
+ * Y position of the Node's Mount Point
+ *
+ * @remarks
+ * The value can be any number between `0.0` and `1.0`:
+ * - `0.0` defines the Mount Point's Y position as the top-most edge of the
+ * Node
+ * - `0.5` defines it as the vertical center of the Node
+ * - `1.0` defines it as the bottom-most edge of the Node.
+ *
+ * The combination of {@link mountX} and {@link mountY} define the Mount Point
+ *
+ * @default 0 (top-most edge)
+ */
+ mountY: number;
+ /**
+ * Combined position of the Node's Pivot Point
+ *
+ * @remarks
+ * The value can be any number between `0.0` and `1.0`:
+ * - `0.0` defines the Pivot Point at the top-left corner of the Node.
+ * - `0.5` defines it at the center of the Node.
+ * - `1.0` defines it at the bottom-right corner of the node.
+ *
+ * Use the {@link pivotX} and {@link pivotY} props seperately for more control
+ * of the Pivot Point.
+ *
+ * When assigned, the same value is also passed to both the {@link pivotX} and
+ * {@link pivotY} props.
+ *
+ * @default 0.5 (center)
+ */
+ pivot: number;
+ /**
+ * X position of the Node's Pivot Point
+ *
+ * @remarks
+ * The value can be any number between `0.0` and `1.0`:
+ * - `0.0` defines the Pivot Point's X position as the left-most edge of the
+ * Node
+ * - `0.5` defines it as the horizontal center of the Node
+ * - `1.0` defines it as the right-most edge of the Node.
+ *
+ * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
+ *
+ * @default 0.5 (centered on x-axis)
+ */
+ pivotX: number;
+ /**
+ * Y position of the Node's Pivot Point
+ *
+ * @remarks
+ * The value can be any number between `0.0` and `1.0`:
+ * - `0.0` defines the Pivot Point's Y position as the top-most edge of the
+ * Node
+ * - `0.5` defines it as the vertical center of the Node
+ * - `1.0` defines it as the bottom-most edge of the Node.
+ *
+ * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
+ *
+ * @default 0.5 (centered on y-axis)
+ */
+ pivotY: number;
+ /**
+ * Rotation of the Node (in Radians)
+ *
+ * @remarks
+ * Sets the amount to rotate the Node by around it's Pivot Point (defined by
+ * the {@link pivot} props). Positive values rotate the Node clockwise, while
+ * negative values rotate it counter-clockwise.
+ *
+ * Example values:
+ * - `-Math.PI / 2`: 90 degree rotation counter-clockwise
+ * - `0`: No rotation
+ * - `Math.PI / 2`: 90 degree rotation clockwise
+ * - `Math.PI`: 180 degree rotation clockwise
+ * - `3 * Math.PI / 2`: 270 degree rotation clockwise
+ * - `2 * Math.PI`: 360 rotation clockwise
+ */
+ rotation: number;
+
+ /**
+ * Whether the Node is rendered to a texture
+ *
+ * @remarks
+ * TBD
+ *
+ * @default false
+ */
+ rtt: boolean;
+
+ /**
+ * Node data element for custom data storage (optional)
+ *
+ * @remarks
+ * This property is used to store custom data on the Node as a key/value data store.
+ * Data values are limited to string, numbers, booleans. Strings will be truncated
+ * to a 2048 character limit for performance reasons.
+ *
+ * This is not a data storage mechanism for large amounts of data please use a
+ * dedicated data storage mechanism for that.
+ *
+ * The custom data will be reflected in the inspector as part of `data-*` attributes
+ *
+ * @default `undefined`
+ */
+ data?: CustomDataMap;
+}
+
+/**
+ * Grab all the number properties of type T
+ */
+type NumberProps = {
+ [Key in keyof T as NonNullable extends number ? Key : never]: number;
+};
+
+/**
+ * Properties of a Node used by the animate() function
+ */
+export interface CoreNodeAnimateProps extends NumberProps {
+ /**
+ * Shader properties to animate
+ */
+ shaderProps: Record;
+ // TODO: textureProps: Record;
+}
+
+/**
+ * A visual Node in the Renderer scene graph.
+ *
+ * @remarks
+ * CoreNode is an internally used class that represents a Renderer Node in the
+ * scene graph. See INode.ts for the public APIs exposed to Renderer users
+ * that include generic types for Shaders.
+ */
+export class CoreNode extends EventEmitter {
readonly children: CoreNode[] = [];
- protected props: Required;
+ protected _id: number = getNewId();
+ readonly props: CoreNodeProps;
public updateType = UpdateType.All;
@@ -267,47 +674,46 @@ export class CoreNode extends EventEmitter implements ICoreNode {
public hasRTTupdates = false;
public parentHasRenderTexture = false;
- constructor(protected stage: Stage, props: CoreNodeProps) {
+ constructor(readonly stage: Stage, props: CoreNodeProps) {
super();
+
this.props = {
...props,
parent: null,
+ texture: null,
+ src: null,
+ rtt: false,
};
- // Allow for parent to be processed appropriately
- this.parent = props.parent;
- // Allow for Render Texture to be processed appropriately
+ // Assign props to instance
+ this.parent = props.parent;
+ this.texture = props.texture;
+ this.src = props.src;
this.rtt = props.rtt;
this.updateScaleRotateTransform();
}
//#region Textures
- loadTexture(
- textureType: Type,
- props: ExtractProps,
- options: TextureOptions | null = null,
- ): void {
- // First unload any existing texture
- if (this.props.texture) {
- this.unloadTexture();
- }
- const { txManager } = this.stage;
- const texture = txManager.loadTexture(textureType, props, options);
-
- this.props.texture = texture;
- this.props.textureOptions = options;
- this.setUpdateType(UpdateType.IsRenderable);
+ loadTexture(): void {
+ const { texture } = this.props;
+ assertTruthy(texture);
// If texture is already loaded / failed, trigger loaded event manually
// so that users get a consistent event experience.
// We do this in a microtask to allow listeners to be attached in the same
// synchronous task after calling loadTexture()
queueMicrotask(() => {
+ // Preload texture if required
+ if (this.textureOptions.preload) {
+ texture.ctxTexture.load();
+ }
if (texture.state === 'loaded') {
- this.onTextureLoaded(texture, texture.dimensions!);
+ assertTruthy(texture.dimensions);
+ this.onTextureLoaded(texture, texture.dimensions);
} else if (texture.state === 'failed') {
- this.onTextureFailed(texture, texture.error!);
+ assertTruthy(texture.error);
+ this.onTextureFailed(texture, texture.error);
} else if (texture.state === 'freed') {
this.onTextureFreed(texture);
}
@@ -318,16 +724,12 @@ export class CoreNode extends EventEmitter implements ICoreNode {
}
unloadTexture(): void {
- if (this.props.texture) {
- const { texture } = this.props;
- texture.off('loaded', this.onTextureLoaded);
- texture.off('failed', this.onTextureFailed);
- texture.off('freed', this.onTextureFreed);
- texture.setRenderableOwner(this, false);
+ if (this.texture) {
+ this.texture.off('loaded', this.onTextureLoaded);
+ this.texture.off('failed', this.onTextureFailed);
+ this.texture.off('freed', this.onTextureFreed);
+ this.texture.setRenderableOwner(this, false);
}
- this.props.texture = null;
- this.props.textureOptions = null;
- this.setUpdateType(UpdateType.IsRenderable);
}
autosizeNode(dimensions: Dimensions) {
@@ -337,7 +739,7 @@ export class CoreNode extends EventEmitter implements ICoreNode {
}
}
- private onTextureLoaded: TextureLoadedEventHandler = (target, dimensions) => {
+ private onTextureLoaded: TextureLoadedEventHandler = (_, dimensions) => {
this.autosizeNode(dimensions);
// Texture was loaded. In case the RAF loop has already stopped, we request
@@ -361,32 +763,20 @@ export class CoreNode extends EventEmitter implements ICoreNode {
}
};
- private onTextureFailed: TextureFailedEventHandler = (target, error) => {
+ private onTextureFailed: TextureFailedEventHandler = (_, error) => {
this.emit('failed', {
type: 'texture',
error,
} satisfies NodeTextureFailedPayload);
};
- private onTextureFreed: TextureFreedEventHandler = (target: Texture) => {
+ private onTextureFreed: TextureFreedEventHandler = () => {
this.emit('freed', {
type: 'texture',
} satisfies NodeTextureFreedPayload);
};
//#endregion Textures
- loadShader(
- shaderType: Type,
- props: ExtractProps,
- ): void {
- const shManager = this.stage.renderer.getShaderManager();
- assertTruthy(shManager);
- const { shader, props: p } = shManager.loadShader(shaderType, props);
- this.props.shader = shader;
- this.props.shaderProps = p;
- this.setUpdateType(UpdateType.IsRenderable);
- }
-
/**
* Change types types is used to determine the scope of the changes being applied
*
@@ -416,29 +806,45 @@ export class CoreNode extends EventEmitter implements ICoreNode {
}
updateScaleRotateTransform() {
+ const { rotation, scaleX, scaleY } = this.props;
+
+ // optimize simple translation cases
+ if (rotation === 0 && scaleX === 1 && scaleY === 1) {
+ this.scaleRotateTransform = undefined;
+ return;
+ }
+
this.scaleRotateTransform = Matrix3d.rotate(
- this.props.rotation,
+ rotation,
this.scaleRotateTransform,
- ).scale(this.props.scaleX, this.props.scaleY);
+ ).scale(scaleX, scaleY);
}
updateLocalTransform() {
- assertTruthy(this.scaleRotateTransform);
- const pivotTranslateX = this.props.pivotX * this.props.width;
- const pivotTranslateY = this.props.pivotY * this.props.height;
- const mountTranslateX = this.props.mountX * this.props.width;
- const mountTranslateY = this.props.mountY * this.props.height;
-
- this.localTransform = Matrix3d.translate(
- pivotTranslateX - mountTranslateX + this.props.x,
- pivotTranslateY - mountTranslateY + this.props.y,
- this.localTransform,
- )
- .multiply(this.scaleRotateTransform)
- .translate(-pivotTranslateX, -pivotTranslateY);
+ const { x, y, width, height } = this.props;
+ const mountTranslateX = this.props.mountX * width;
+ const mountTranslateY = this.props.mountY * height;
+
+ if (this.scaleRotateTransform) {
+ const pivotTranslateX = this.props.pivotX * width;
+ const pivotTranslateY = this.props.pivotY * height;
+
+ this.localTransform = Matrix3d.translate(
+ x - mountTranslateX + pivotTranslateX,
+ y - mountTranslateY + pivotTranslateY,
+ this.localTransform,
+ )
+ .multiply(this.scaleRotateTransform)
+ .translate(-pivotTranslateX, -pivotTranslateY);
+ } else {
+ this.localTransform = Matrix3d.translate(
+ x - mountTranslateX,
+ y - mountTranslateY,
+ this.localTransform,
+ );
+ }
// Handle 'contain' resize mode
- const { width, height } = this.props;
const texture = this.props.texture;
if (
texture &&
@@ -650,7 +1056,7 @@ export class CoreNode extends EventEmitter implements ICoreNode {
return false;
}
- if (this.props.shader) {
+ if (this.props.shader !== this.stage.defShaderCtr) {
return true;
}
@@ -710,19 +1116,19 @@ export class CoreNode extends EventEmitter implements ICoreNode {
this.strictBound,
);
+ if (boundInsideBound(this.renderBound, this.strictBound)) {
+ return CoreNodeRenderState.InViewport;
+ }
+
const renderM = this.stage.boundsMargin;
this.preloadBound = createBound(
- parentClippingRect.x - renderM[3],
- parentClippingRect.y - renderM[0],
- parentClippingRect.x + rectW + renderM[1],
- parentClippingRect.y + rectH + renderM[2],
+ this.strictBound.x1 - renderM[3],
+ this.strictBound.y1 - renderM[0],
+ this.strictBound.x2 + renderM[1],
+ this.strictBound.y2 + renderM[2],
this.preloadBound,
);
- if (boundInsideBound(this.renderBound, this.strictBound)) {
- return CoreNodeRenderState.InViewport;
- }
-
if (boundInsideBound(this.renderBound, this.preloadBound)) {
return CoreNodeRenderState.InBounds;
}
@@ -731,48 +1137,19 @@ export class CoreNode extends EventEmitter implements ICoreNode {
updateRenderState(parentClippingRect: RectWithValid) {
const renderState = this.checkRenderBounds(parentClippingRect);
- if (renderState !== this.renderState) {
- let previous = this.renderState;
- this.renderState = renderState;
- if (previous === CoreNodeRenderState.InViewport) {
- this.emit('outOfViewport', {
- previous,
- current: renderState,
- });
- }
- if (
- previous < CoreNodeRenderState.InBounds &&
- renderState === CoreNodeRenderState.InViewport
- ) {
- this.emit(CoreNodeRenderStateMap.get(CoreNodeRenderState.InBounds)!, {
- previous,
- current: renderState,
- });
- previous = CoreNodeRenderState.InBounds;
- } else if (
- previous > CoreNodeRenderState.InBounds &&
- renderState === CoreNodeRenderState.OutOfBounds
- ) {
- this.emit(CoreNodeRenderStateMap.get(CoreNodeRenderState.InBounds)!, {
- previous,
- current: renderState,
- });
- previous = CoreNodeRenderState.InBounds;
- }
- const event = CoreNodeRenderStateMap.get(renderState);
- assertTruthy(event);
- this.emit(event, {
- previous,
- current: renderState,
- });
- }
- }
- setRenderState(state: CoreNodeRenderState) {
- if (state !== this.renderState) {
- this.renderState = state;
- this.emit(CoreNodeRenderState[state]);
+ if (renderState === this.renderState) {
+ return;
}
+
+ const previous = this.renderState;
+ this.renderState = renderState;
+ const event = CoreNodeRenderStateMap.get(renderState);
+ assertTruthy(event);
+ this.emit(event, {
+ previous,
+ current: renderState,
+ });
}
/**
@@ -794,7 +1171,7 @@ export class CoreNode extends EventEmitter implements ICoreNode {
}
onChangeIsRenderable(isRenderable: boolean) {
- this.props.texture?.setRenderableOwner(this, isRenderable);
+ this.texture?.setRenderableOwner(this, isRenderable);
}
calculateRenderCoords() {
@@ -927,19 +1304,25 @@ export class CoreNode extends EventEmitter implements ICoreNode {
delete this.localTransform;
this.props.texture = null;
- this.props.shader = null;
+ this.props.shader = this.stage.defShaderCtr;
+
+ const children = [...this.children];
+ for (let i = 0; i < children.length; i++) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ children[i]!.destroy();
+ }
+ // This very action will also remove the node from the parent's children array
+ this.parent = null;
if (this.rtt) {
this.stage.renderer.removeRTTNode(this);
}
this.removeAllListeners();
- this.parent = null;
}
renderQuads(renderer: CoreRenderer): void {
- const { width, height, texture, textureOptions, shader, shaderProps, rtt } =
- this.props;
+ const { texture, width, height, textureOptions, rtt, shader } = this.props;
// Prevent quad rendering if parent has a render texture
// and renderer is not currently rendering to a texture
@@ -960,9 +1343,16 @@ export class CoreNode extends EventEmitter implements ICoreNode {
premultipliedColorBr,
} = this;
- const { zIndex, worldAlpha, globalTransform: gt, clippingRect } = this;
+ const {
+ zIndex,
+ worldAlpha,
+ globalTransform: gt,
+ clippingRect,
+ renderCoords,
+ } = this;
assertTruthy(gt);
+ assertTruthy(renderCoords);
// add to list of renderables to be sorted before rendering
renderer.addQuad({
@@ -975,8 +1365,8 @@ export class CoreNode extends EventEmitter implements ICoreNode {
texture,
textureOptions,
zIndex,
- shader,
- shaderProps,
+ shader: shader.shader,
+ shaderProps: shader.getResolvedProps(),
alpha: worldAlpha,
clippingRect,
tx: gt.tx,
@@ -985,6 +1375,7 @@ export class CoreNode extends EventEmitter implements ICoreNode {
tb: gt.tb,
tc: gt.tc,
td: gt.td,
+ renderCoords,
rtt,
parentHasRenderTexture: this.parentHasRenderTexture,
framebufferDimensions: this.framebufferDimensions,
@@ -993,7 +1384,7 @@ export class CoreNode extends EventEmitter implements ICoreNode {
//#region Properties
get id(): number {
- return this.props.id;
+ return this._id;
}
get x(): number {
@@ -1039,6 +1430,11 @@ export class CoreNode extends EventEmitter implements ICoreNode {
this.setUpdateType(UpdateType.Local);
if (this.props.rtt) {
+ this.texture = this.stage.txManager.loadTexture('RenderTexture', {
+ width: this.width,
+ height: this.height,
+ });
+ this.textureOptions.preload = true;
this.setUpdateType(UpdateType.RenderTexture);
}
}
@@ -1054,6 +1450,11 @@ export class CoreNode extends EventEmitter implements ICoreNode {
this.setUpdateType(UpdateType.Local);
if (this.props.rtt) {
+ this.texture = this.stage.txManager.loadTexture('RenderTexture', {
+ width: this.width,
+ height: this.height,
+ });
+ this.textureOptions.preload = true;
this.setUpdateType(UpdateType.RenderTexture);
}
}
@@ -1206,17 +1607,10 @@ export class CoreNode extends EventEmitter implements ICoreNode {
}
set color(value: number) {
- if (
- this.props.colorTl !== value ||
- this.props.colorTr !== value ||
- this.props.colorBl !== value ||
- this.props.colorBr !== value
- ) {
- this.colorTl = value;
- this.colorTr = value;
- this.colorBl = value;
- this.colorBr = value;
- }
+ this.colorTop = value;
+ this.colorBottom = value;
+ this.colorLeft = value;
+ this.colorRight = value;
this.props.color = value;
this.setUpdateType(UpdateType.PremultipliedColors);
@@ -1378,9 +1772,11 @@ export class CoreNode extends EventEmitter implements ICoreNode {
}
set rtt(value: boolean) {
- if (!value) {
- if (this.props.rtt) {
- this.props.rtt = false;
+ if (this.props.rtt === true) {
+ this.props.rtt = value;
+
+ // unload texture if we used to have a render texture
+ if (value === false && this.texture !== null) {
this.unloadTexture();
this.setUpdateType(UpdateType.All);
@@ -1389,10 +1785,22 @@ export class CoreNode extends EventEmitter implements ICoreNode {
});
this.stage.renderer?.removeRTTNode(this);
+ return;
}
+ }
+
+ // if the new value is false and we didnt have rtt previously, we don't need to do anything
+ if (value === false) {
return;
}
+ // load texture
+ this.texture = this.stage.txManager.loadTexture('RenderTexture', {
+ width: this.width,
+ height: this.height,
+ });
+ this.textureOptions.preload = true;
+
this.props.rtt = true;
this.hasRTTupdates = true;
this.setUpdateType(UpdateType.All);
@@ -1405,6 +1813,41 @@ export class CoreNode extends EventEmitter implements ICoreNode {
this.stage.renderer?.renderToTexture(this);
}
+ get shader(): BaseShaderController {
+ return this.props.shader;
+ }
+
+ set shader(value: BaseShaderController) {
+ if (this.props.shader === value) {
+ return;
+ }
+
+ this.props.shader = value;
+
+ this.setUpdateType(UpdateType.IsRenderable);
+ }
+
+ get src(): string | null {
+ return this.props.src;
+ }
+
+ set src(imageUrl: string | null) {
+ if (this.props.src === imageUrl) {
+ return;
+ }
+
+ this.props.src = imageUrl;
+
+ if (!imageUrl) {
+ this.texture = null;
+ return;
+ }
+
+ this.texture = this.stage.txManager.loadTexture('ImageTexture', {
+ src: imageUrl,
+ });
+ }
+
/**
* Returns the framebuffer dimensions of the node.
* If the node has a render texture, the dimensions are the same as the node's dimensions.
@@ -1436,9 +1879,53 @@ export class CoreNode extends EventEmitter implements ICoreNode {
return this.props.texture;
}
+ set texture(value: Texture | null) {
+ if (this.props.texture === value) {
+ return;
+ }
+ const oldTexture = this.props.texture;
+ if (oldTexture) {
+ oldTexture.setRenderableOwner(this, false);
+ this.unloadTexture();
+ }
+ this.props.texture = value;
+ if (value) {
+ value.setRenderableOwner(this, this.isRenderable);
+ this.loadTexture();
+ }
+ this.setUpdateType(UpdateType.IsRenderable);
+ }
+
+ set textureOptions(value: TextureOptions) {
+ this.props.textureOptions = value;
+ }
+
+ get textureOptions(): TextureOptions {
+ return this.props.textureOptions;
+ }
+
setRTTUpdates(type: number) {
this.hasRTTupdates = true;
this.parent?.setRTTUpdates(type);
}
+
+ animate(
+ props: Partial,
+ settings: Partial,
+ ): IAnimationController {
+ const animation = new CoreAnimation(this, props, settings);
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
+ const controller = new CoreAnimationController(
+ this.stage.animationManager,
+ animation,
+ );
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ return controller;
+ }
+
+ flush() {
+ // no-op
+ }
+
//#endregion Properties
}
diff --git a/src/core/CoreShaderManager.ts b/src/core/CoreShaderManager.ts
index 8a71e504..f9a8ef0c 100644
--- a/src/core/CoreShaderManager.ts
+++ b/src/core/CoreShaderManager.ts
@@ -66,6 +66,11 @@ import {
} from './renderers/webgl/shaders/effects/HolePunchEffect.js';
import { WebGlCoreShader } from './renderers/webgl/WebGlCoreShader.js';
import { UnsupportedShader } from './renderers/canvas/shaders/UnsupportedShader.js';
+import { ShaderController } from '../main-api/ShaderController.js';
+import {
+ DynamicShaderController,
+ type DynamicEffects,
+} from '../main-api/DynamicShaderController.js';
export type { FadeOutEffectProps };
export type { LinearGradientEffectProps };
@@ -84,11 +89,6 @@ export interface ShaderMap {
UnsupportedShader: typeof UnsupportedShader;
}
-export type ShaderNode = {
- shader: InstanceType;
- props: Record;
-};
-
export interface EffectMap {
radius: typeof RadiusEffect;
border: typeof BorderEffect;
@@ -166,10 +166,17 @@ export class CoreShaderManager {
return this.shConstructors;
}
+ /**
+ * Loads a shader (if not already loaded) and returns a controller for it.
+ *
+ * @param shType
+ * @param props
+ * @returns
+ */
loadShader(
shType: Type,
props?: ExtractProps,
- ): ShaderNode {
+ ): ShaderController {
if (!this.renderer) {
throw new Error(`Renderer is not been defined`);
}
@@ -182,14 +189,17 @@ export class CoreShaderManager {
this.renderer.mode === 'canvas' &&
ShaderClass.prototype instanceof WebGlCoreShader
) {
- return {
- shader: new UnsupportedShader(shType) as InstanceType,
- props: props as Record,
- };
+ return this._createShaderCtr(
+ shType,
+ new UnsupportedShader(shType) as InstanceType,
+ props as ExtractProps,
+ );
}
if (shType === 'DynamicShader') {
- return this.loadDynamicShader(props!);
+ return this.loadDynamicShader(
+ props!,
+ ) as unknown as ShaderController;
}
const resolvedProps = ShaderClass.resolveDefaults(
@@ -198,10 +208,11 @@ export class CoreShaderManager {
const cacheKey =
ShaderClass.makeCacheKey(resolvedProps) || ShaderClass.name;
if (cacheKey && this.shCache.has(cacheKey)) {
- return {
- shader: this.shCache.get(cacheKey) as InstanceType,
- props: resolvedProps,
- };
+ return this._createShaderCtr(
+ shType,
+ this.shCache.get(cacheKey) as InstanceType,
+ resolvedProps as ExtractProps,
+ );
}
// @ts-expect-error ShaderClass WILL accept a Renderer
@@ -211,15 +222,16 @@ export class CoreShaderManager {
if (cacheKey) {
this.shCache.set(cacheKey, shader);
}
- return {
+ return this._createShaderCtr(
+ shType,
shader,
- props: resolvedProps,
- };
+ resolvedProps as ExtractProps,
+ );
}
- loadDynamicShader(
- props: DynamicShaderProps,
- ): ShaderNode {
+ loadDynamicShader<
+ T extends DynamicEffects<[...{ name?: string; type: keyof EffectMap }[]]>,
+ >(props: DynamicShaderProps): DynamicShaderController {
if (!this.renderer) {
throw new Error(`Renderer is not been defined`);
}
@@ -232,10 +244,10 @@ export class CoreShaderManager {
this.effectConstructors,
);
if (cacheKey && this.shCache.has(cacheKey)) {
- return {
- shader: this.shCache.get(cacheKey) as InstanceType,
- props: resolvedProps,
- };
+ return this._createDynShaderCtr(
+ this.shCache.get(cacheKey) as InstanceType,
+ resolvedProps,
+ );
}
const shader = new DynamicShader(
this.renderer as WebGlCoreRenderer,
@@ -245,10 +257,25 @@ export class CoreShaderManager {
if (cacheKey) {
this.shCache.set(cacheKey, shader);
}
- return {
- shader: shader as InstanceType,
- props: resolvedProps,
- };
+
+ return this._createDynShaderCtr(shader, resolvedProps);
+ }
+
+ private _createShaderCtr(
+ type: Type,
+ shader: InstanceType,
+ props: ExtractProps,
+ ): ShaderController {
+ return new ShaderController(type, shader, props, this.renderer.stage);
+ }
+
+ private _createDynShaderCtr<
+ T extends DynamicEffects<[...{ name?: string; type: keyof EffectMap }[]]>,
+ >(
+ shader: InstanceType,
+ props: ExtractProps,
+ ): DynamicShaderController {
+ return new DynamicShaderController(shader, props, this);
}
useShader(shader: CoreShader): void {
diff --git a/src/core/CoreTextNode.ts b/src/core/CoreTextNode.ts
index a498390b..c2507833 100644
--- a/src/core/CoreTextNode.ts
+++ b/src/core/CoreTextNode.ts
@@ -32,21 +32,44 @@ import type {
NodeTextFailedPayload,
NodeTextLoadedPayload,
} from '../common/CommonTypes.js';
-import type { Rect, RectWithValid } from './lib/utils.js';
+import type { RectWithValid } from './lib/utils.js';
import { assertTruthy } from '../utils.js';
import { Matrix3d } from './lib/Matrix3d.js';
export interface CoreTextNodeProps extends CoreNodeProps, TrProps {
- text: string;
+ /**
+ * Force Text Node to use a specific Text Renderer
+ *
+ * @remarks
+ * By default, Text Nodes resolve the Text Renderer to use based on the font
+ * that is matched using the font family and other font selection properties.
+ *
+ * If two fonts supported by two separate Text Renderers are matched setting
+ * this override forces the Text Node to resolve to the Text Renderer defined
+ * here.
+ *
+ * @default null
+ */
textRendererOverride: keyof TextRendererMap | null;
}
-type ICoreTextNode = Omit<
- CoreTextNodeProps,
- 'texture' | 'textureOptions' | 'shader' | 'shaderProps'
->;
-
-export class CoreTextNode extends CoreNode implements ICoreTextNode {
+/**
+ * An CoreNode in the Renderer scene graph that renders text.
+ *
+ * @remarks
+ * A Text Node is the second graphical building block of the Renderer scene
+ * graph. It renders text using a specific text renderer that is automatically
+ * chosen based on the font requested and what type of fonts are installed
+ * into an app.
+ *
+ * The text renderer can be overridden by setting the `textRendererOverride`
+ *
+ * The `texture` and `shader` properties are managed by loaded text renderer and
+ * should not be set directly.
+ *
+ * For non-text rendering, see {@link CoreNode}.
+ */
+export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
textRenderer: TextRenderer;
trState: TextRendererState;
private _textRendererOverride: CoreTextNodeProps['textRendererOverride'] =
@@ -356,6 +379,15 @@ export class CoreTextNode extends CoreNode implements ICoreTextNode {
override renderQuads(renderer: CoreRenderer) {
assertTruthy(this.globalTransform);
+ // If the text renderer does not support rendering quads, fallback to the
+ // default renderQuads method
+ if (!this.textRenderer.renderQuads) {
+ super.renderQuads(renderer);
+ return;
+ }
+
+ // If the text renderer does support rendering quads, use it...
+
// Prevent quad rendering if parent has a render texture
// and this node is not the render texture
if (this.parentHasRenderTexture) {
@@ -410,7 +442,7 @@ export class CoreTextNode extends CoreNode implements ICoreTextNode {
this._textRendererOverride,
);
- const textRendererState = resolvedTextRenderer.createState(props);
+ const textRendererState = resolvedTextRenderer.createState(props, this);
textRendererState.emitter.on('loaded', this.onTextLoaded);
textRendererState.emitter.on('failed', this.onTextFailed);
diff --git a/src/core/CoreTextureManager.ts b/src/core/CoreTextureManager.ts
index 404b3e64..8934e1ed 100644
--- a/src/core/CoreTextureManager.ts
+++ b/src/core/CoreTextureManager.ts
@@ -17,9 +17,7 @@
* limitations under the License.
*/
-import { assertTruthy } from '../utils.js';
import { ImageWorkerManager } from './lib/ImageWorker.js';
-import type { CoreContextTexture } from './renderers/CoreContextTexture.js';
import type { CoreRenderer } from './renderers/CoreRenderer.js';
import { ColorTexture } from './textures/ColorTexture.js';
import { ImageTexture } from './textures/ImageTexture.js';
@@ -29,7 +27,7 @@ import { RenderTexture } from './textures/RenderTexture.js';
import type { Texture } from './textures/Texture.js';
/**
- * Augmentable map of texture types
+ * Augmentable map of texture class types
*
* @remarks
* This interface can be augmented by other modules/apps to add additional
@@ -54,7 +52,6 @@ export type ExtractProps = Type extends { z$__type__Props: infer Props }
*/
export interface TextureManagerDebugInfo {
keyCacheSize: number;
- idCacheSize: number;
}
export type ResizeModeOptions =
@@ -117,35 +114,6 @@ export interface TextureOptions {
*/
preload?: boolean;
- /**
- * ID to use for this texture.
- *
- * @remarks
- * This is for internal use only as an optimization.
- *
- * @privateRemarks
- * This is used to avoid having to look up the texture in the texture cache
- * by its cache key. Theoretically this should be faster.
- *
- * @defaultValue Automatically generated
- */
- id?: number;
-
- /**
- * Cache key to use for this texture
- *
- * @remarks
- * If this is set, the texture will be cached using this key. If a texture
- * with the same key is already cached, it will be returned instead of
- * creating a new texture.
- *
- * If this is not set (undefined), it will be automatically generated via
- * the specified `Texture`'s `makeCacheKey()` method.
- *
- * @defaultValue Automatically generated via `Texture.makeCacheKey()`
- */
- cacheKey?: string | false;
-
/**
* Flip the texture horizontally when rendering
*
@@ -172,20 +140,20 @@ export interface TextureOptions {
export class CoreTextureManager {
/**
- * Amount of used memory defined in pixels
+ * Map of textures by cache key
*/
- usedMemory = 0;
+ keyCache: Map = new Map();
- txConstructors: Partial = {};
+ /**
+ * Map of cache keys by texture
+ */
+ inverseKeyCache: WeakMap = new WeakMap();
- textureKeyCache: Map = new Map();
- textureIdCache: Map = new Map();
+ /**
+ * Map of texture constructors by their type name
+ */
+ txConstructors: Partial = {};
- ctxTextureCache: WeakMap = new WeakMap();
- textureRefCountMap: WeakMap<
- Texture,
- { cacheKey: string | false; count: number }
- > = new WeakMap();
imageWorkerManager: ImageWorkerManager | null = null;
hasCreateImageBitmap = !!self.createImageBitmap;
hasWorker = !!self.Worker;
@@ -198,6 +166,17 @@ export class CoreTextureManager {
*/
renderer!: CoreRenderer;
+ /**
+ * The current frame time in milliseconds
+ *
+ * @remarks
+ * This is used to populate the `lastRenderableChangeTime` property of
+ * {@link Texture} instances when their renderable state changes.
+ *
+ * Set by stage via `updateFrameTime` method.
+ */
+ frameTime = 0;
+
constructor(numImageWorkers: number) {
// Register default known texture types
if (this.hasCreateImageBitmap && this.hasWorker && numImageWorkers > 0) {
@@ -227,155 +206,49 @@ export class CoreTextureManager {
loadTexture(
textureType: Type,
props: ExtractProps,
- options: TextureOptions | null = null,
): InstanceType {
+ let texture: Texture | undefined;
const TextureClass = this.txConstructors[textureType];
if (!TextureClass) {
throw new Error(`Texture type "${textureType}" is not registered`);
}
- let texture: Texture | undefined;
- // If an ID is specified, try to get the texture from the ID cache first
- if (options?.id !== undefined && this.textureIdCache.has(options.id)) {
- // console.log('Getting texture by texture desc ID', options.id);
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- texture = this.textureIdCache.get(options.id)!;
- }
- // If the texture is not found in the ID cache, try to get it from the key cache
+
if (!texture) {
- const descId = options?.id;
- const cacheKey =
- options?.cacheKey ?? TextureClass.makeCacheKey(props as any);
- if (cacheKey && this.textureKeyCache.has(cacheKey)) {
+ const cacheKey = TextureClass.makeCacheKey(props as any);
+ if (cacheKey && this.keyCache.has(cacheKey)) {
// console.log('Getting texture by cache key', cacheKey);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- texture = this.textureKeyCache.get(cacheKey)!;
+ texture = this.keyCache.get(cacheKey)!;
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
texture = new TextureClass(this, props as any);
- }
- if (descId) {
- this.addTextureIdToCache(descId, cacheKey, texture);
- }
- }
- if (options?.preload) {
- const ctxTx = this.getCtxTexture(texture);
- ctxTx.load();
- }
- return texture as InstanceType;
- }
-
- /**
- * Add a `Texture` to the texture cache by its texture desc ID and cache key
- *
- * @remarks
- * This is used internally by the `CoreTextureManager` to cache textures
- * when they are created.
- *
- * It handles updating the texture ID cache, texture key cache, and texture
- * reference count map.
- *
- * @param textureDescId
- * @param cacheKey
- * @param texture
- */
- private addTextureIdToCache(
- textureDescId: number,
- cacheKey: string | false,
- texture: Texture,
- ): void {
- const { textureIdCache, textureRefCountMap } = this;
- textureIdCache.set(textureDescId, texture);
- if (textureRefCountMap.has(texture)) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- textureRefCountMap.get(texture)!.count++;
- } else {
- textureRefCountMap.set(texture, { cacheKey, count: 1 });
- if (cacheKey) {
- this.textureKeyCache.set(cacheKey, texture);
- }
- }
- }
-
- /**
- * Remove a `Texture` from the texture cache by its texture desc ID
- *
- * @remarks
- * This is called externally by when we know (at least reasonably well) that
- * the `TextureRef` in the Main API space has been is no longer used. This
- * allows us to remove the `Texture` from the Usage Cache so that it can be
- * garbage collected as well.
- *
- * @param textureDescId
- */
- removeTextureIdFromCache(textureDescId: number): void {
- const { textureIdCache, textureRefCountMap } = this;
- const texture = textureIdCache.get(textureDescId);
- if (!texture) {
- // Sometimes a texture is removed from the cache before it ever gets
- // added to the cache. This is fine and not an error.
- return;
- }
- textureIdCache.delete(textureDescId);
- if (textureRefCountMap.has(texture)) {
- const refCountObj = textureRefCountMap.get(texture);
- assertTruthy(refCountObj);
- refCountObj.count--;
- if (refCountObj.count === 0) {
- textureRefCountMap.delete(texture);
- // If the texture is not referenced anywhere else, remove it from the key cache
- // as well.
- // This should allow the `Texture` instance to be garbage collected.
- if (refCountObj.cacheKey) {
- this.textureKeyCache.delete(refCountObj.cacheKey);
+ if (cacheKey) {
+ this.initTextureToCache(texture, cacheKey);
}
}
}
- // Free the ctx texture if it exists.
- this.ctxTextureCache.get(texture)?.free();
+ return texture as InstanceType;
}
- /**
- * Get an object containing debug information about the texture manager.
- *
- * @returns
- */
- getDebugInfo(): TextureManagerDebugInfo {
- // const textureSet = new Set();
- // for (const texture of this.textureIdCache.values()) {
- // textureSet.add(texture);
- // }
- // for (const texture of this.textureKeyCache.values()) {
- // textureSet.add(texture);
- // }
- // TODO: Output number of bytes used by textures
- return {
- keyCacheSize: this.textureKeyCache.size,
- idCacheSize: this.textureIdCache.size,
- };
+ private initTextureToCache(texture: Texture, cacheKey: string) {
+ const { keyCache, inverseKeyCache } = this;
+ keyCache.set(cacheKey, texture);
+ inverseKeyCache.set(texture, cacheKey);
}
/**
- * Get a CoreContextTexture for the given Texture source.
+ * Remove a texture from the cache
*
* @remarks
- * If the texture source already has an allocated CoreContextTexture, it will be
- * returned from the cache. Otherwise, a new CoreContextTexture will be created
- * and cached.
- *
- * ContextTextures are stored in a WeakMap, so they will be garbage collected
- * when the Texture source is no longer referenced.
+ * Called by Texture Cleanup when a texture is freed.
*
- * @param textureSource
- * @returns
+ * @param texture
*/
- getCtxTexture(textureSource: Texture): CoreContextTexture {
- if (this.ctxTextureCache.has(textureSource)) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return this.ctxTextureCache.get(textureSource)!;
+ removeTextureFromCache(texture: Texture) {
+ const { inverseKeyCache, keyCache } = this;
+ const cacheKey = inverseKeyCache.get(texture);
+ if (cacheKey) {
+ keyCache.delete(cacheKey);
}
- const texture = this.renderer.createCtxTexture(textureSource);
-
- this.ctxTextureCache.set(textureSource, texture);
- return texture;
}
}
diff --git a/src/core/Stage.ts b/src/core/Stage.ts
index a9961fd1..b306edae 100644
--- a/src/core/Stage.ts
+++ b/src/core/Stage.ts
@@ -20,10 +20,10 @@ import { startLoop, getTimeStamp } from './platform.js';
import { WebGlCoreRenderer } from './renderers/webgl/WebGlCoreRenderer.js';
import { assertTruthy, setPremultiplyMode } from '../utils.js';
import { AnimationManager } from './animations/AnimationManager.js';
-import { CoreNode } from './CoreNode.js';
+import { CoreNode, type CoreNodeProps } from './CoreNode.js';
import { CoreTextureManager } from './CoreTextureManager.js';
import { TrFontManager } from './text-rendering/TrFontManager.js';
-import { CoreShaderManager } from './CoreShaderManager.js';
+import { CoreShaderManager, type ShaderMap } from './CoreShaderManager.js';
import type {
TextRenderer,
TextRendererMap,
@@ -37,18 +37,23 @@ import type {
FpsUpdatePayload,
FrameTickPayload,
} from '../common/CommonTypes.js';
-import { TextureMemoryManager } from './TextureMemoryManager.js';
+import {
+ TextureMemoryManager,
+ type TextureMemoryManagerSettings,
+} from './TextureMemoryManager.js';
import type {
CoreRenderer,
CoreRendererOptions,
} from './renderers/CoreRenderer.js';
import { CanvasCoreRenderer } from './renderers/canvas/CanvasCoreRenderer.js';
+import type { BaseShaderController } from '../main-api/ShaderController.js';
+import { CoreTextNode, type CoreTextNodeProps } from './CoreTextNode.js';
+import { santizeCustomDataMap } from '../main-api/utils.js';
export interface StageOptions {
- rootId: number;
appWidth: number;
appHeight: number;
- txMemByteThreshold: number;
+ textureMemory: TextureMemoryManagerSettings;
boundsMargin: number | [number, number, number, number];
deviceLogicalPixelRatio: number;
devicePhysicalPixelRatio: number;
@@ -58,10 +63,8 @@ export interface StageOptions {
enableContextSpy: boolean;
numImageWorkers: number;
renderMode: 'webgl' | 'canvas';
-
- debug?: {
- monitorTextureCache?: boolean;
- };
+ eventBus: EventEmitter;
+ quadBufferSize: number;
}
export type StageFpsUpdateHandler = (
@@ -77,7 +80,7 @@ export type StageFrameTickHandler = (
const bufferMemory = 2e6;
const autoStart = true;
-export class Stage extends EventEmitter {
+export class Stage {
/// Module Instances
public readonly animationManager: AnimationManager;
public readonly txManager: CoreTextureManager;
@@ -88,6 +91,17 @@ export class Stage extends EventEmitter {
public readonly renderer: CoreRenderer;
public readonly root: CoreNode;
public readonly boundsMargin: [number, number, number, number];
+ public readonly defShaderCtr: BaseShaderController;
+
+ /**
+ * Renderer Event Bus for the Stage to emit events onto
+ *
+ * @remarks
+ * In reality this is just the RendererMain instance, which is an EventEmitter.
+ * this allows us to directly emit events from the Stage to RendererMain
+ * without having to set up forwarding handlers.
+ */
+ public readonly eventBus: EventEmitter;
/// State
deltaTime = 0;
@@ -96,6 +110,7 @@ export class Stage extends EventEmitter {
private fpsNumFrames = 0;
private fpsElapsedTime = 0;
private renderRequested = false;
+ private frameEventQueue: [name: string, payload: unknown][] = [];
/// Debug data
contextSpy: ContextSpy | null = null;
@@ -104,23 +119,21 @@ export class Stage extends EventEmitter {
* Stage constructor
*/
constructor(readonly options: StageOptions) {
- super();
const {
canvas,
clearColor,
- rootId,
- debug,
appWidth,
appHeight,
boundsMargin,
enableContextSpy,
numImageWorkers,
- txMemByteThreshold,
+ textureMemory,
renderMode,
} = options;
+ this.eventBus = options.eventBus;
this.txManager = new CoreTextureManager(numImageWorkers);
- this.txMemManager = new TextureMemoryManager(txMemByteThreshold);
+ this.txMemManager = new TextureMemoryManager(this, textureMemory);
this.shManager = new CoreShaderManager();
this.animationManager = new AnimationManager();
this.contextSpy = enableContextSpy ? new ContextSpy() : null;
@@ -133,15 +146,6 @@ export class Stage extends EventEmitter {
}
this.boundsMargin = bm;
- if (debug?.monitorTextureCache) {
- setInterval(() => {
- assertTruthy(this.txManager);
- const debugInfo = this.txManager.getDebugInfo();
- console.log('Texture ID Cache Size: ', debugInfo.idCacheSize);
- console.log('Texture Key Cache Size: ', debugInfo.keyCacheSize);
- }, 1000);
- }
-
const rendererOptions: CoreRendererOptions = {
stage: this,
canvas,
@@ -160,6 +164,7 @@ export class Stage extends EventEmitter {
} else {
this.renderer = new WebGlCoreRenderer(rendererOptions);
}
+ this.defShaderCtr = this.renderer.getDefShaderCtr();
setPremultiplyMode(renderMode);
// Must do this after renderer is created
@@ -178,7 +183,6 @@ export class Stage extends EventEmitter {
// create root node
const rootNode = new CoreNode(this, {
- id: rootId,
x: 0,
y: 0,
width: appWidth,
@@ -208,10 +212,11 @@ export class Stage extends EventEmitter {
rotation: 0,
parent: null,
texture: null,
- textureOptions: null,
- shader: null,
- shaderProps: null,
+ textureOptions: {},
+ shader: this.defShaderCtr,
rtt: false,
+ src: null,
+ scale: 1,
});
this.root = rootNode;
@@ -222,6 +227,24 @@ export class Stage extends EventEmitter {
}
}
+ updateFrameTime() {
+ const newFrameTime = getTimeStamp();
+ this.lastFrameTime = this.currentFrameTime;
+ this.currentFrameTime = newFrameTime;
+ this.deltaTime = !this.lastFrameTime
+ ? 100 / 6
+ : newFrameTime - this.lastFrameTime;
+ this.txManager.frameTime = newFrameTime;
+ this.txMemManager.frameTime = newFrameTime;
+
+ // This event is emitted at the beginning of the frame (before any updates
+ // or rendering), so no need to to use `stage.queueFrameEvent` here.
+ this.eventBus.emit('frameTick', {
+ time: this.currentFrameTime,
+ delta: this.deltaTime,
+ });
+ }
+
/**
* Update animations
*/
@@ -230,17 +253,6 @@ export class Stage extends EventEmitter {
if (!this.root) {
return;
}
- this.lastFrameTime = this.currentFrameTime;
- this.currentFrameTime = getTimeStamp();
-
- this.deltaTime = !this.lastFrameTime
- ? 100 / 6
- : this.currentFrameTime - this.lastFrameTime;
-
- this.emit('frameTick', {
- time: this.currentFrameTime,
- delta: this.deltaTime,
- });
// step animation
animationManager.update(this.deltaTime);
}
@@ -267,9 +279,9 @@ export class Stage extends EventEmitter {
// Reset render operations and clear the canvas
renderer.reset();
- // Check if we need to garbage collect
- if (renderer.txMemManager.gcRequested) {
- renderer.txMemManager.gc();
+ // Check if we need to cleanup textures
+ if (this.txMemManager.criticalCleanupRequested) {
+ this.txMemManager.cleanup();
}
// If we have RTT nodes draw them first
@@ -292,6 +304,40 @@ export class Stage extends EventEmitter {
}
}
+ /**
+ * Queue an event to be emitted after the current/next frame is rendered
+ *
+ * @remarks
+ * When we are operating in the context of the render loop, we may want to
+ * emit events that are related to the current frame. However, we generally do
+ * NOT want to emit events directly in the middle of the render loop, since
+ * this could enable event handlers to modify the scene graph and cause
+ * unexpected behavior. Instead, we queue up events to be emitted and then
+ * flush the queue after the frame has been rendered.
+ *
+ * @param name
+ * @param data
+ */
+ queueFrameEvent(name: string, data: unknown) {
+ this.frameEventQueue.push([name, data]);
+ }
+
+ /**
+ * Emit all queued frame events
+ *
+ * @remarks
+ * This method should be called after the frame has been rendered to emit
+ * all events that were queued during the frame.
+ *
+ * See {@link queueFrameEvent} for more information.
+ */
+ flushFrameEvents() {
+ for (const [name, data] of this.frameEventQueue) {
+ this.eventBus.emit(name, data);
+ }
+ this.frameEventQueue = [];
+ }
+
calculateFps() {
// If there's an FPS update interval, emit the FPS update event
// when the specified interval has elapsed.
@@ -305,7 +351,7 @@ export class Stage extends EventEmitter {
);
this.fpsNumFrames = 0;
this.fpsElapsedTime = 0;
- this.emit('fpsUpdate', {
+ this.queueFrameEvent('fpsUpdate', {
fps,
contextSpyData: this.contextSpy?.getData() ?? null,
} satisfies FpsUpdatePayload);
@@ -407,4 +453,115 @@ export class Stage extends EventEmitter {
// the covariant state argument in the setter method map
return resolvedTextRenderer as unknown as TextRenderer;
}
+
+ /**
+ * Create a shader controller instance
+ *
+ * @param type
+ * @param props
+ * @returns
+ */
+ createShaderCtr(
+ type: keyof ShaderMap,
+ props: Record,
+ ): BaseShaderController {
+ return this.shManager.loadShader(type, props);
+ }
+
+ createNode(props: Partial) {
+ const resolvedProps = this.resolveNodeDefaults(props);
+ return new CoreNode(this, resolvedProps);
+ }
+
+ createTextNode(props: Partial) {
+ const fontSize = props.fontSize ?? 16;
+ const resolvedProps = {
+ ...this.resolveNodeDefaults(props),
+ text: props.text ?? '',
+ textRendererOverride: props.textRendererOverride ?? null,
+ fontSize,
+ fontFamily: props.fontFamily ?? 'sans-serif',
+ fontStyle: props.fontStyle ?? 'normal',
+ fontWeight: props.fontWeight ?? 'normal',
+ fontStretch: props.fontStretch ?? 'normal',
+ textAlign: props.textAlign ?? 'left',
+ contain: props.contain ?? 'none',
+ scrollable: props.scrollable ?? false,
+ scrollY: props.scrollY ?? 0,
+ offsetY: props.offsetY ?? 0,
+ letterSpacing: props.letterSpacing ?? 0,
+ lineHeight: props.lineHeight, // `undefined` is a valid value
+ maxLines: props.maxLines ?? 0,
+ textBaseline: props.textBaseline ?? 'alphabetic',
+ verticalAlign: props.verticalAlign ?? 'middle',
+ overflowSuffix: props.overflowSuffix ?? '...',
+ debug: props.debug ?? {},
+ shaderProps: null,
+ };
+
+ return new CoreTextNode(this, resolvedProps);
+ }
+
+ /**
+ * Resolves the default property values for a Node
+ *
+ * @remarks
+ * This method is used internally by the RendererMain to resolve the default
+ * property values for a Node. It is exposed publicly so that it can be used
+ * by Core Driver implementations.
+ *
+ * @param props
+ * @returns
+ */
+ protected resolveNodeDefaults(props: Partial): CoreNodeProps {
+ const color = props.color ?? 0xffffffff;
+ const colorTl = props.colorTl ?? props.colorTop ?? props.colorLeft ?? color;
+ const colorTr =
+ props.colorTr ?? props.colorTop ?? props.colorRight ?? color;
+ const colorBl =
+ props.colorBl ?? props.colorBottom ?? props.colorLeft ?? color;
+ const colorBr =
+ props.colorBr ?? props.colorBottom ?? props.colorRight ?? color;
+ const data = santizeCustomDataMap(props.data ?? {});
+
+ return {
+ x: props.x ?? 0,
+ y: props.y ?? 0,
+ width: props.width ?? 0,
+ height: props.height ?? 0,
+ alpha: props.alpha ?? 1,
+ autosize: props.autosize ?? false,
+ clipping: props.clipping ?? false,
+ color,
+ colorTop: props.colorTop ?? color,
+ colorBottom: props.colorBottom ?? color,
+ colorLeft: props.colorLeft ?? color,
+ colorRight: props.colorRight ?? color,
+ colorBl,
+ colorBr,
+ colorTl,
+ colorTr,
+ zIndex: props.zIndex ?? 0,
+ zIndexLocked: props.zIndexLocked ?? 0,
+ parent: props.parent ?? null,
+ texture: props.texture ?? null,
+ textureOptions: props.textureOptions ?? {},
+ shader: props.shader ?? this.defShaderCtr,
+ // Since setting the `src` will trigger a texture load, we need to set it after
+ // we set the texture. Otherwise, problems happen.
+ src: props.src ?? null,
+ scale: props.scale ?? null,
+ scaleX: props.scaleX ?? props.scale ?? 1,
+ scaleY: props.scaleY ?? props.scale ?? 1,
+ mount: props.mount ?? 0,
+ mountX: props.mountX ?? props.mount ?? 0,
+ mountY: props.mountY ?? props.mount ?? 0,
+ pivot: props.pivot ?? 0.5,
+ pivotX: props.pivotX ?? props.pivot ?? 0.5,
+ pivotY: props.pivotY ?? props.pivot ?? 0.5,
+ rotation: props.rotation ?? 0,
+ rtt: props.rtt ?? false,
+ data: data,
+ };
+ }
}
diff --git a/src/core/TextureMemoryManager.ts b/src/core/TextureMemoryManager.ts
index c59e15c9..765136d8 100644
--- a/src/core/TextureMemoryManager.ts
+++ b/src/core/TextureMemoryManager.ts
@@ -16,53 +16,262 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import type { CoreContextTexture } from './renderers/CoreContextTexture.js';
+import type { Stage } from './Stage.js';
+import type { Texture } from './textures/Texture.js';
+import { bytesToMb } from './utils.js';
+export interface TextureMemoryManagerSettings {
+ /**
+ * Critical Threshold (in bytes)
+ *
+ * @remarks
+ * When the amount of memory used by textures exceeds this threshold,
+ * the Renderer will immediately trigger a Texture Cleanup towards the
+ * Target Threshold Level.
+ *
+ * When set to `0`, the Texture Memory Manager is disabled.
+ *
+ * @defaultValue `124e6` (118 MB)
+ */
+ criticalThreshold: number;
+
+ /**
+ * Target Threshold Level (as fraction of Critical Threshold)
+ *
+ * @remarks
+ * This value is the fractional level of the Critical Threshold that the
+ * Texture Memory Manager will attempt to maintain by cleaning up textures.
+ * The Texture Memory Manager will attempt to keep the memory usage below
+ * this level by freeing up non-renderable textures.
+ *
+ * Valid Range: 0.0 - 1.0
+ *
+ * @defaultValue `0.5`
+ */
+ targetThresholdLevel: number;
+
+ /**
+ * Interval between Texture Cleanups (in milliseconds)
+ *
+ * @remarks
+ * Texture Memory Manager will perform a Texture Cleanup no more
+ * frequently than this interval generally when the scene becomes idle.
+ *
+ * @defaultValue `30,000` (30 seconds)
+ */
+ cleanupInterval: number;
+
+ /**
+ * Whether or not to log debug information
+ *
+ * @defaultValue `false`
+ */
+ debugLogging: boolean;
+}
+
+export interface MemoryInfo {
+ criticalThreshold: number;
+ targetThreshold: number;
+ renderableMemUsed: number;
+ memUsed: number;
+ renderableTexturesLoaded: number;
+ loadedTextures: number;
+}
+
+/**
+ * LRU (Least Recently Used) style memory manager for textures
+ *
+ * @remarks
+ * This class is responsible for managing the memory usage of textures
+ * in the Renderer. It keeps track of the memory used by each texture
+ * and triggers a cleanup when the memory usage exceeds a critical
+ * threshold (`criticalThreshold`).
+ *
+ * The cleanup process will free up non-renderable textures until the
+ * memory usage is below a target threshold (`targetThresholdLevel`).
+ *
+ * The memory manager's clean up process will also be triggered when the
+ * scene is idle for a certain amount of time (`cleanupInterval`).
+ */
export class TextureMemoryManager {
private memUsed = 0;
- private textures: Map = new Map();
- private threshold: number;
- public gcRequested = false;
-
+ private loadedTextures: Map = new Map();
+ private criticalThreshold: number;
+ private targetThreshold: number;
+ private cleanupInterval: number;
+ private debugLogging: boolean;
+ private lastCleanupTime = 0;
+ public criticalCleanupRequested = false;
/**
- * @param byteThreshold Number of texture bytes to trigger garbage collection
+ * The current frame time in milliseconds
+ *
+ * @remarks
+ * This is used to determine when to perform Idle Texture Cleanups.
+ *
+ * Set by stage via `updateFrameTime` method.
*/
- constructor(byteThreshold: number) {
- this.threshold = byteThreshold;
+ public frameTime = 0;
+
+ constructor(private stage: Stage, settings: TextureMemoryManagerSettings) {
+ const { criticalThreshold } = settings;
+ this.criticalThreshold = Math.round(criticalThreshold);
+ const targetFraction = Math.max(
+ 0,
+ Math.min(1, settings.targetThresholdLevel),
+ );
+ this.targetThreshold = Math.round(criticalThreshold * targetFraction);
+ this.cleanupInterval = settings.cleanupInterval;
+ this.debugLogging = settings.debugLogging;
+
+ if (settings.debugLogging) {
+ let lastMemUse = 0;
+ setInterval(() => {
+ if (lastMemUse !== this.memUsed) {
+ lastMemUse = this.memUsed;
+ console.log(
+ `[TextureMemoryManager] Memory used: ${bytesToMb(
+ this.memUsed,
+ )} mb / ${bytesToMb(this.criticalThreshold)} mb (${(
+ (this.memUsed / this.criticalThreshold) *
+ 100
+ ).toFixed(1)}%)`,
+ );
+ }
+ }, 1000);
+ }
// If the threshold is 0, we disable the memory manager by replacing the
// setTextureMemUse method with a no-op function.
- if (byteThreshold === 0) {
+ if (criticalThreshold === 0) {
// eslint-disable-next-line @typescript-eslint/no-empty-function
this.setTextureMemUse = () => {};
}
}
- setTextureMemUse(ctxTexture: CoreContextTexture, byteSize: number) {
- if (this.textures.has(ctxTexture)) {
+ setTextureMemUse(texture: Texture, byteSize: number) {
+ if (this.loadedTextures.has(texture)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.memUsed -= this.textures.get(ctxTexture)!;
+ this.memUsed -= this.loadedTextures.get(texture)!;
}
if (byteSize === 0) {
- this.textures.delete(ctxTexture);
+ this.loadedTextures.delete(texture);
return;
} else {
this.memUsed += byteSize;
- this.textures.set(ctxTexture, byteSize);
+ this.loadedTextures.set(texture, byteSize);
}
- if (this.memUsed > this.threshold) {
- this.gcRequested = true;
+ if (this.memUsed > this.criticalThreshold) {
+ this.criticalCleanupRequested = true;
}
}
- gc() {
- this.gcRequested = false;
- this.textures.forEach((byteSize, ctxTexture) => {
- if (!ctxTexture.renderable) {
- ctxTexture.free();
+ checkCleanup() {
+ return (
+ this.criticalCleanupRequested ||
+ (this.memUsed > this.targetThreshold &&
+ this.frameTime - this.lastCleanupTime >= this.cleanupInterval)
+ );
+ }
+
+ cleanup() {
+ const critical = this.criticalCleanupRequested;
+ this.lastCleanupTime = this.frameTime;
+ this.criticalCleanupRequested = false;
+
+ if (critical) {
+ this.stage.queueFrameEvent('criticalCleanup', {
+ memUsed: this.memUsed,
+ criticalThreshold: this.criticalThreshold,
+ });
+ }
+
+ if (this.debugLogging) {
+ console.log(
+ `[TextureMemoryManager] Cleaning up textures. Critical: ${critical}`,
+ );
+ }
+
+ /**
+ * Sort the loaded textures by renderability, then by last touch time.
+ *
+ * This will ensure that the array is ordered by the following:
+ * - Non-renderable textures, starting at the least recently rendered
+ * - Renderable textures, starting at the least recently rendered
+ */
+ const textures = [...this.loadedTextures.keys()].sort(
+ (textureA, textureB) => {
+ const txARenderable = textureA.renderable;
+ const txBRenderable = textureB.renderable;
+ if (txARenderable === txBRenderable) {
+ return (
+ textureA.lastRenderableChangeTime -
+ textureB.lastRenderableChangeTime
+ );
+ } else if (txARenderable) {
+ return 1;
+ } else if (txBRenderable) {
+ return -1;
+ }
+ return 0;
+ },
+ );
+
+ // Free non-renderable textures until we reach the target threshold
+ const memTarget = this.targetThreshold;
+ const txManager = this.stage.txManager;
+ for (const texture of textures) {
+ if (texture.renderable) {
+ // Stop at the first renderable texture (The rest are renderable because of the sort above)
+ // We don't want to free renderable textures because they will just likely be reloaded in the next frame
+ break;
+ }
+ texture.ctxTexture.free();
+ txManager.removeTextureFromCache(texture);
+ if (this.memUsed <= memTarget) {
+ // Stop once we've freed enough textures to reach under the target threshold
+ break;
}
- });
+ }
+
+ if (this.memUsed >= this.criticalThreshold) {
+ this.stage.queueFrameEvent('criticalCleanupFailed', {
+ memUsed: this.memUsed,
+ criticalThreshold: this.criticalThreshold,
+ });
+ console.warn(
+ `[TextureMemoryManager] Memory usage above critical threshold after cleanup: ${this.memUsed}`,
+ );
+ }
+ }
+
+ /**
+ * Get the current texture memory usage information
+ *
+ * @remarks
+ * This method is for debugging purposes and returns information about the
+ * current memory usage of the textures in the Renderer.
+ */
+ getMemoryInfo(): MemoryInfo {
+ let renderableTexturesLoaded = 0;
+ const renderableMemUsed = [...this.loadedTextures.keys()].reduce(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (acc, texture) => {
+ renderableTexturesLoaded += texture.renderable ? 1 : 0;
+ return (
+ acc + (texture.renderable ? this.loadedTextures.get(texture)! : 0)
+ );
+ },
+ 0,
+ );
+ return {
+ criticalThreshold: this.criticalThreshold,
+ targetThreshold: this.targetThreshold,
+ renderableMemUsed,
+ memUsed: this.memUsed,
+ renderableTexturesLoaded,
+ loadedTextures: this.loadedTextures.size,
+ };
}
}
diff --git a/src/core/animations/CoreAnimation.ts b/src/core/animations/CoreAnimation.ts
index 29402826..29cb4706 100644
--- a/src/core/animations/CoreAnimation.ts
+++ b/src/core/animations/CoreAnimation.ts
@@ -17,8 +17,7 @@
* limitations under the License.
*/
-import type { CoreNode } from '../CoreNode.js';
-import type { INodeAnimatableProps } from '../../main-api/INode.js';
+import { type CoreNode, type CoreNodeAnimateProps } from '../CoreNode.js';
import { getTimingFunction } from '../utils.js';
import { mergeColorProgress } from '../../utils.js';
import { EventEmitter } from '../../common/EventEmitter.js';
@@ -33,26 +32,68 @@ export interface AnimationSettings {
stopMethod: 'reverse' | 'reset' | false;
}
+type PropValues = {
+ start: number;
+ target: number;
+};
+type PropValuesMap = Record>;
+
export class CoreAnimation extends EventEmitter {
- public propStartValues: Partial = {};
- public restoreValues: Partial = {};
public settings: AnimationSettings;
private progress = 0;
private delayFor = 0;
private timingFunction: (t: number) => number | undefined;
- private propsList: Array; //fixme - aint got not time for this
+
+ propValuesMap: PropValuesMap = {};
+ dynPropValuesMap: PropValuesMap | undefined = undefined;
constructor(
private node: CoreNode,
- private props: Partial,
+ private props: Partial,
settings: Partial,
) {
super();
- this.propStartValues = {};
- this.propsList = Object.keys(props) as Array;
- this.propsList.forEach((propName) => {
- this.propStartValues[propName] = node[propName];
- });
+
+ for (const key in props) {
+ if (key !== 'shaderProps') {
+ if (this.propValuesMap['props'] === undefined) {
+ this.propValuesMap['props'] = {};
+ }
+ this.propValuesMap['props'][key] = {
+ start: node[key as keyof Omit],
+ target: props[
+ key as keyof Omit
+ ] as number,
+ };
+ } else if (node.shader.type !== 'DynamicShader') {
+ this.propValuesMap['shaderProps'] = {};
+ for (const key in props.shaderProps) {
+ this.propValuesMap['shaderProps'][key] = {
+ start: node.shader.props[key] as number,
+ target: props.shaderProps[key] as number,
+ };
+ }
+ } else {
+ const shaderPropKeys = Object.keys(props.shaderProps!);
+ const spLength = shaderPropKeys.length;
+ this.dynPropValuesMap = {};
+ for (let j = 0; j < spLength; j++) {
+ const effectName = shaderPropKeys[j]!;
+ const effect = props.shaderProps![effectName]!;
+ this.dynPropValuesMap[effectName] = {};
+ const effectProps = Object.entries(effect);
+ const eLength = effectProps.length;
+
+ for (let k = 0; k < eLength; k++) {
+ const [key, value] = effectProps[k]!;
+ this.dynPropValuesMap[effectName]![key] = {
+ start: node.shader.props[effectName][key],
+ target: value,
+ };
+ }
+ }
+ }
+ }
const easing = settings.easing || 'linear';
const delay = settings.delay ?? 0;
@@ -75,28 +116,82 @@ export class CoreAnimation extends EventEmitter {
this.update(0);
}
+ private restoreValues(
+ target: Record,
+ valueMap: Record,
+ ) {
+ const entries = Object.entries(valueMap);
+ const eLength = entries.length;
+
+ for (let i = 0; i < eLength; i++) {
+ const [key, value] = entries[i]!;
+ target[key] = value.start;
+ }
+ }
+
restore() {
this.reset();
- (Object.keys(this.props) as Array).forEach(
- (propName) => {
- this.node[propName] = this.propStartValues[propName] as number;
- },
- );
+ if (this.propValuesMap['props'] !== undefined) {
+ this.restoreValues(
+ this.node as unknown as Record,
+ this.propValuesMap['props'],
+ );
+ }
+ if (this.propValuesMap['shaderProps'] !== undefined) {
+ this.restoreValues(
+ this.node.shader.props as Record,
+ this.propValuesMap['shaderProps'],
+ );
+ }
+
+ if (this.dynPropValuesMap !== undefined) {
+ const dynEntries = Object.keys(this.dynPropValuesMap);
+ const dynEntriesL = dynEntries.length;
+ if (dynEntriesL > 0) {
+ for (let i = 0; i < dynEntriesL; i++) {
+ const key = dynEntries[i]!;
+ this.restoreValues(
+ this.node.shader.props[key],
+ this.dynPropValuesMap[key]!,
+ );
+ }
+ }
+ }
+ }
+
+ private reverseValues(valueMap: Record) {
+ const entries = Object.entries(valueMap);
+ const eLength = entries.length;
+
+ for (let i = 0; i < eLength; i++) {
+ const [key, value] = entries[i]!;
+ valueMap[key] = {
+ start: value.target,
+ target: value.start,
+ };
+ }
}
reverse() {
this.progress = 0;
- (Object.keys(this.props) as Array).forEach(
- (propName) => {
- // set the start value to the current value
- const startValue = this.props[propName];
- const endValue = this.propStartValues[propName] as number;
-
- // swap the start and end values
- this.props[propName] = endValue;
- this.propStartValues[propName] = startValue;
- },
- );
+
+ if (this.propValuesMap['props'] !== undefined) {
+ this.reverseValues(this.propValuesMap['props']);
+ }
+ if (this.propValuesMap['shaderProps'] !== undefined) {
+ this.reverseValues(this.propValuesMap['shaderProps']);
+ }
+
+ if (this.dynPropValuesMap !== undefined) {
+ const dynEntries = Object.keys(this.dynPropValuesMap);
+ const dynEntriesL = dynEntries.length;
+ if (dynEntriesL > 0) {
+ for (let i = 0; i < dynEntriesL; i++) {
+ const key = dynEntries[i]!;
+ this.reverseValues(this.dynPropValuesMap[key]!);
+ }
+ }
+ }
// restore stop method if we are not looping
if (!this.settings.loop) {
@@ -108,6 +203,53 @@ export class CoreAnimation extends EventEmitter {
return (this.timingFunction(p) || p) * (e - s) + s;
}
+ updateValue(
+ propName: string,
+ propValue: number,
+ startValue: number,
+ easing: string | undefined,
+ ): number {
+ if (this.progress === 1) {
+ return propValue;
+ }
+ if (this.progress === 0) {
+ return startValue;
+ }
+
+ const endValue = propValue;
+ if (propName.indexOf('color') !== -1) {
+ if (startValue === endValue) {
+ return startValue;
+ }
+
+ if (easing) {
+ const easingProgressValue =
+ this.timingFunction(this.progress) || this.progress;
+ return mergeColorProgress(startValue, endValue, easingProgressValue);
+ }
+ return mergeColorProgress(startValue, endValue, this.progress);
+ }
+
+ if (easing) {
+ return this.applyEasing(this.progress, startValue, endValue);
+ }
+ return startValue + (endValue - startValue) * this.progress;
+ }
+
+ private updateValues(
+ target: Record,
+ valueMap: Record,
+ easing: string | undefined,
+ ) {
+ const entries = Object.entries(valueMap);
+ const eLength = entries.length;
+
+ for (let i = 0; i < eLength; i++) {
+ const [key, value] = entries[i]!;
+ target[key] = this.updateValue(key, value.target, value.start, easing);
+ }
+ }
+
update(dt: number) {
const { duration, loop, easing, stopMethod } = this.settings;
const { delayFor } = this;
@@ -153,51 +295,36 @@ export class CoreAnimation extends EventEmitter {
}
}
- for (let i = 0; i < this.propsList.length; i++) {
- const propName = this.propsList[i] as keyof INodeAnimatableProps;
- const propValue = this.props[propName] as number;
- const startValue = this.propStartValues[propName] as number;
- const endValue = propValue;
-
- if (propName.indexOf('color') !== -1) {
- // check if we have to change the color to begin with
- if (startValue === endValue) {
- this.node[propName] = startValue;
- continue;
- }
+ if (this.propValuesMap['props'] !== undefined) {
+ this.updateValues(
+ this.node as unknown as Record,
+ this.propValuesMap['props'],
+ easing,
+ );
+ }
+ if (this.propValuesMap['shaderProps'] !== undefined) {
+ this.updateValues(
+ this.node.shader.props as Record,
+ this.propValuesMap['shaderProps'],
+ easing,
+ );
+ }
- if (easing) {
- const easingProgressValue =
- this.timingFunction(this.progress) || this.progress;
- const easingColorValue = mergeColorProgress(
- startValue,
- endValue,
- easingProgressValue,
+ if (this.dynPropValuesMap !== undefined) {
+ const dynEntries = Object.keys(this.dynPropValuesMap);
+ const dynEntriesL = dynEntries.length;
+ if (dynEntriesL > 0) {
+ for (let i = 0; i < dynEntriesL; i++) {
+ const key = dynEntries[i]!;
+ this.updateValues(
+ this.node.shader.props[key],
+ this.dynPropValuesMap[key]!,
+ easing,
);
- this.node[propName] = easingColorValue;
- continue;
}
-
- this.node[propName] = mergeColorProgress(
- startValue,
- endValue,
- this.progress,
- );
- continue;
}
-
- if (easing) {
- this.node[propName] = this.applyEasing(
- this.progress,
- startValue,
- endValue,
- );
- continue;
- }
-
- this.node[propName] =
- startValue + (endValue - startValue) * this.progress;
}
+
if (this.progress === 1) {
this.emit('finished', {});
}
diff --git a/src/core/lib/ImageWorker.ts b/src/core/lib/ImageWorker.ts
index 92414b98..c212a7f3 100644
--- a/src/core/lib/ImageWorker.ts
+++ b/src/core/lib/ImageWorker.ts
@@ -20,6 +20,84 @@
import { type TextureData } from '../textures/Texture.js';
type MessageCallback = [(value: any) => void, (reason: any) => void];
+interface getImageReturn {
+ data: ImageBitmap;
+ premultiplyAlpha: boolean | null;
+}
+
+/**
+ * Note that, within the createImageWorker function, we must only use ES5 code to keep it ES5-valid after babelifying, as
+ * the converted code of this section is converted to a blob and used as the js of the web worker thread.
+ *
+ * The createImageWorker function is a web worker that fetches an image from a URL and returns an ImageBitmap object.
+ * The eslint @typescript rule is disabled for the entire function because the function is converted to a blob and used as the
+ * js of the web worker thread, so the typescript syntax is not valid in this context.
+ */
+
+/* eslint-disable */
+function createImageWorker() {
+ function hasAlphaChannel(mimeType: string) {
+ return mimeType.indexOf('image/png') !== -1;
+ }
+
+ function getImage(
+ src: string,
+ premultiplyAlpha: boolean | null,
+ ): Promise {
+ return new Promise(function (resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', src, true);
+ xhr.responseType = 'blob';
+
+ xhr.onload = function () {
+ if (xhr.status !== 200) {
+ return reject(new Error('Failed to load image: ' + xhr.statusText));
+ }
+
+ var blob = xhr.response;
+ var withAlphaChannel =
+ premultiplyAlpha !== undefined
+ ? premultiplyAlpha
+ : hasAlphaChannel(blob.type);
+
+ createImageBitmap(blob, {
+ premultiplyAlpha: withAlphaChannel ? 'premultiply' : 'none',
+ colorSpaceConversion: 'none',
+ imageOrientation: 'none',
+ })
+ .then(function (data) {
+ resolve({ data, premultiplyAlpha: premultiplyAlpha });
+ })
+ .catch(function (error) {
+ reject(error);
+ });
+ };
+
+ xhr.onerror = function () {
+ reject(
+ new Error('Network error occurred while trying to fetch the image.'),
+ );
+ };
+
+ xhr.send();
+ });
+ }
+
+ self.onmessage = (event) => {
+ var src = event.data.src;
+ var id = event.data.id;
+ var premultiplyAlpha = event.data.premultiplyAlpha;
+
+ getImage(src, premultiplyAlpha)
+ .then(function (data) {
+ self.postMessage({ id: id, src: src, data: data });
+ })
+ .catch(function (error) {
+ self.postMessage({ id: id, src: src, error: error.message });
+ });
+ };
+}
+/* eslint-enable */
export class ImageWorkerManager {
imageWorkersEnabled = true;
@@ -55,58 +133,7 @@ export class ImageWorkerManager {
}
private createWorkers(numWorkers = 1): Worker[] {
- const workerCode = `
- function hasAlphaChannel(mimeType) {
- return (mimeType.indexOf("image/png") !== -1);
- }
-
- function getImage(src, premultiplyAlpha) {
- return new Promise(function(resolve, reject) {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', src, true);
- xhr.responseType = 'blob';
-
- xhr.onload = function() {
- if (xhr.status === 200) {
- var blob = xhr.response;
- var hasAlphaChannel = premultiplyAlpha !== undefined ? premultiplyAlpha : hasAlphaChannel(blob.type);
-
- createImageBitmap(blob, {
- premultiplyAlpha: hasAlphaChannel ? 'premultiply' : 'none',
- colorSpaceConversion: 'none',
- imageOrientation: 'none'
- }).then(function(data) {
- resolve({ data: data, premultiplyAlpha: premultiplyAlpha });
- }).catch(function(error) {
- reject(error);
- });
- } else {
- reject(new Error('Failed to load image: ' + xhr.statusText));
- }
- };
-
- xhr.onerror = function() {
- reject(new Error('Network error occurred while trying to fetch the image.'));
- };
-
- xhr.send();
- });
- }
-
- self.onmessage = (event) => {
- var id = event.data.id;
- var src = event.data.src;
- var premultiplyAlpha = event.data.premultiplyAlpha;
-
- getImage(src, premultiplyAlpha)
- .then(function(data) {
- self.postMessage({ id: id, data: data }, [data.data]);
- })
- .catch(function(error) {
- self.postMessage({ id: id, error: error.message });
- });
- };
- `;
+ const workerCode = `(${createImageWorker.toString()})()`;
const blob: Blob = new Blob([workerCode.replace('"use strict";', '')], {
type: 'application/javascript',
diff --git a/src/core/lib/utils.ts b/src/core/lib/utils.ts
index 4e0f3773..d02bbc29 100644
--- a/src/core/lib/utils.ts
+++ b/src/core/lib/utils.ts
@@ -20,6 +20,7 @@
export const PROTOCOL_REGEX = /^(data|ftps?|https?):/;
export type RGBA = [r: number, g: number, b: number, a: number];
+
export const getNormalizedRgbaComponents = (rgba: number): RGBA => {
const r = rgba >>> 24;
const g = (rgba >>> 16) & 0xff;
diff --git a/src/core/platform.ts b/src/core/platform.ts
index 57596bc0..5f54236f 100644
--- a/src/core/platform.ts
+++ b/src/core/platform.ts
@@ -25,21 +25,28 @@ import type { Stage } from './Stage.js';
export const startLoop = (stage: Stage) => {
let isIdle = false;
const runLoop = () => {
+ stage.updateFrameTime();
stage.updateAnimations();
if (!stage.hasSceneUpdates()) {
// We still need to calculate the fps else it looks like the app is frozen
stage.calculateFps();
setTimeout(runLoop, 16.666666666666668);
+
if (!isIdle) {
- stage.emit('idle');
+ if (stage.txMemManager.checkCleanup()) {
+ stage.txMemManager.cleanup();
+ }
+ stage.eventBus.emit('idle');
isIdle = true;
}
+ stage.flushFrameEvents();
return;
}
isIdle = false;
stage.drawFrame();
+ stage.flushFrameEvents();
requestAnimationFrame(runLoop);
};
requestAnimationFrame(runLoop);
diff --git a/src/core/renderers/CoreContextTexture.ts b/src/core/renderers/CoreContextTexture.ts
index c4ff84d3..94ecde3a 100644
--- a/src/core/renderers/CoreContextTexture.ts
+++ b/src/core/renderers/CoreContextTexture.ts
@@ -21,15 +21,22 @@ import type { TextureMemoryManager } from '../TextureMemoryManager.js';
import type { Texture } from '../textures/Texture.js';
export abstract class CoreContextTexture {
- readonly memManager: TextureMemoryManager;
readonly textureSource: Texture;
+ private memManager: TextureMemoryManager;
constructor(memManager: TextureMemoryManager, textureSource: Texture) {
this.memManager = memManager;
this.textureSource = textureSource;
}
+ protected setTextureMemUse(byteSize: number): void {
+ this.memManager.setTextureMemUse(this.textureSource, byteSize);
+ }
+
abstract load(): void;
abstract free(): void;
- abstract get renderable(): boolean;
+
+ get renderable(): boolean {
+ return this.textureSource.renderable;
+ }
}
diff --git a/src/core/renderers/CoreRenderer.ts b/src/core/renderers/CoreRenderer.ts
index 840ea9e4..aa0e3538 100644
--- a/src/core/renderers/CoreRenderer.ts
+++ b/src/core/renderers/CoreRenderer.ts
@@ -18,6 +18,7 @@
*/
import type { Dimensions } from '../../common/CommonTypes.js';
+import type { BaseShaderController } from '../../main-api/ShaderController.js';
import type { CoreNode } from '../CoreNode.js';
import type { CoreShaderManager } from '../CoreShaderManager.js';
import type {
@@ -27,8 +28,8 @@ import type {
import type { Stage } from '../Stage.js';
import type { TextureMemoryManager } from '../TextureMemoryManager.js';
import type { ContextSpy } from '../lib/ContextSpy.js';
+import type { RenderCoords } from '../lib/RenderCoords.js';
import type { RectWithValid } from '../lib/utils.js';
-import { ColorTexture } from '../textures/ColorTexture.js';
import type { Texture } from '../textures/Texture.js';
import { CoreContextTexture } from './CoreContextTexture.js';
import type { CoreShader } from './CoreShader.js';
@@ -53,6 +54,7 @@ export interface QuadOptions {
tb: number;
tc: number;
td: number;
+ renderCoords?: RenderCoords;
rtt?: boolean;
parentHasRenderTexture?: boolean;
framebufferDimensions?: Dimensions;
@@ -70,11 +72,16 @@ export interface CoreRendererOptions {
contextSpy: ContextSpy | null;
}
+export interface BufferInfo {
+ totalUsed: number;
+ totalAvailable: number;
+}
+
export abstract class CoreRenderer {
public options: CoreRendererOptions;
public mode: 'webgl' | 'canvas' | undefined;
- protected stage: Stage;
+ readonly stage: Stage;
//// Core Managers
txManager: CoreTextureManager;
@@ -100,4 +107,6 @@ export abstract class CoreRenderer {
abstract renderRTTNodes(): void;
abstract removeRTTNode(node: CoreNode): void;
abstract renderToTexture(node: CoreNode): void;
+ abstract getBufferInfo(): BufferInfo | null;
+ abstract getDefShaderCtr(): BaseShaderController;
}
diff --git a/src/core/renderers/canvas/CanvasCoreRenderer.ts b/src/core/renderers/canvas/CanvasCoreRenderer.ts
index a43cbe21..0fb82473 100644
--- a/src/core/renderers/canvas/CanvasCoreRenderer.ts
+++ b/src/core/renderers/canvas/CanvasCoreRenderer.ts
@@ -17,6 +17,7 @@
* limitations under the License.
*/
+import type { BaseShaderController } from '../../../main-api/ShaderController.js';
import type { CoreNode } from '../../CoreNode.js';
import type { CoreShaderManager } from '../../CoreShaderManager.js';
import { getRgbaComponents, type RGBA } from '../../lib/utils.js';
@@ -35,6 +36,7 @@ import {
parseColor,
type IParsedColor,
} from './internal/ColorUtils.js';
+import { UnsupportedShader } from './shaders/UnsupportedShader.js';
export class CanvasCoreRenderer extends CoreRenderer {
private context: CanvasRenderingContext2D;
@@ -43,6 +45,8 @@ export class CanvasCoreRenderer extends CoreRenderer {
private clearColor: RGBA | undefined;
public renderToTextureActive = false;
activeRttNode: CoreNode | null = null;
+ private defShaderCtr: BaseShaderController;
+
constructor(options: CoreRendererOptions) {
super(options);
@@ -54,6 +58,17 @@ export class CanvasCoreRenderer extends CoreRenderer {
this.context = canvas.getContext('2d') as CanvasRenderingContext2D;
this.pixelRatio = pixelRatio;
this.clearColor = clearColor ? getRgbaComponents(clearColor) : undefined;
+
+ // Stub for default shader controller since the canvas renderer does not
+ // (really) support the concept of a shader (yet)
+ this.defShaderCtr = {
+ type: 'DefaultShader',
+ props: {},
+ shader: new UnsupportedShader('DefaultShader'),
+ getResolvedProps: () => () => {
+ return {};
+ },
+ };
}
reset(): void {
@@ -104,7 +119,7 @@ export class CanvasCoreRenderer extends CoreRenderer {
texture = texture.parentTexture;
}
- ctxTexture = this.txManager.getCtxTexture(texture) as CanvasCoreTexture;
+ ctxTexture = texture.ctxTexture as CanvasCoreTexture;
if (texture.state === 'freed') {
ctxTexture.load();
return;
@@ -209,6 +224,10 @@ export class CanvasCoreRenderer extends CoreRenderer {
return this.shManager;
}
+ override getDefShaderCtr(): BaseShaderController {
+ return this.defShaderCtr;
+ }
+
renderRTTNodes(): void {
// noop
}
@@ -220,4 +239,7 @@ export class CanvasCoreRenderer extends CoreRenderer {
renderToTexture(node: CoreNode): void {
// noop
}
+ getBufferInfo(): null {
+ return null;
+ }
}
diff --git a/src/core/renderers/canvas/CanvasCoreTexture.ts b/src/core/renderers/canvas/CanvasCoreTexture.ts
index ef77635c..efcf9c4e 100644
--- a/src/core/renderers/canvas/CanvasCoreTexture.ts
+++ b/src/core/renderers/canvas/CanvasCoreTexture.ts
@@ -50,7 +50,7 @@ export class CanvasCoreTexture extends CoreContextTexture {
this.image = undefined;
this.tintCache = undefined;
this.textureSource.setState('freed');
- this.memManager.setTextureMemUse(this, 0);
+ this.setTextureMemUse(0);
}
updateMemSize(): void {
@@ -60,7 +60,7 @@ export class CanvasCoreTexture extends CoreContextTexture {
const mult = this.tintCache ? 8 : 4;
if (this.textureSource.dimensions) {
const { width, height } = this.textureSource.dimensions;
- this.memManager.setTextureMemUse(this, width * height * mult);
+ this.setTextureMemUse(width * height * mult);
}
}
@@ -119,10 +119,6 @@ export class CanvasCoreTexture extends CoreContextTexture {
return canvas;
}
- get renderable(): boolean {
- return this.textureSource.renderable;
- }
-
private async onLoadRequest(): Promise {
const { data } = await this.textureSource.getTextureData();
// TODO: canvas from text renderer should be able to provide the canvas directly
diff --git a/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.ts b/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.ts
index 7ae1ea1b..90809c27 100644
--- a/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.ts
+++ b/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.ts
@@ -42,7 +42,7 @@ export class WebGlCoreCtxRenderTexture extends WebGlCoreCtxTexture {
}
override async onLoadRequest(): Promise {
- const { glw, memManager } = this;
+ const { glw } = this;
const nativeTexture = (this._nativeCtxTexture =
this.createNativeCtxTexture());
const { width, height } = this.textureSource;
@@ -60,7 +60,7 @@ export class WebGlCoreCtxRenderTexture extends WebGlCoreCtxTexture {
);
// Update the texture memory manager
- memManager.setTextureMemUse(this, width * height * 4);
+ this.setTextureMemUse(width * height * 4);
// Bind the framebuffer
glw.bindFramebuffer(this.framebuffer);
diff --git a/src/core/renderers/webgl/WebGlCoreCtxTexture.ts b/src/core/renderers/webgl/WebGlCoreCtxTexture.ts
index 6bde1ac0..c1eb9da5 100644
--- a/src/core/renderers/webgl/WebGlCoreCtxTexture.ts
+++ b/src/core/renderers/webgl/WebGlCoreCtxTexture.ts
@@ -61,10 +61,6 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
return this._nativeCtxTexture;
}
- get renderable(): boolean {
- return this.textureSource.renderable;
- }
-
get w() {
return this._w;
}
@@ -118,11 +114,11 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
* Called when the texture data needs to be loaded and uploaded to a texture
*/
async onLoadRequest(): Promise {
- const { glw, memManager } = this;
+ const { glw } = this;
// Set to a 1x1 transparent texture
glw.texImage2D(0, glw.RGBA, 1, 1, 0, glw.RGBA, glw.UNSIGNED_BYTE, null);
- memManager.setTextureMemUse(this, TRANSPARENT_TEXTURE_DATA.byteLength);
+ this.setTextureMemUse(TRANSPARENT_TEXTURE_DATA.byteLength);
const textureData = await this.textureSource?.getTextureData();
// If the texture has been freed while loading, return early.
@@ -153,7 +149,7 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
);
glw.texImage2D(0, glw.RGBA, glw.RGBA, glw.UNSIGNED_BYTE, data);
- memManager.setTextureMemUse(this, width * height * 4);
+ this.setTextureMemUse(width * height * 4);
// generate mipmaps for power-of-2 textures or in WebGL2RenderingContext
if (glw.isWebGl2() || (isPowerOfTwo(width) && isPowerOfTwo(height))) {
@@ -175,7 +171,7 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
glw.UNSIGNED_BYTE,
TRANSPARENT_TEXTURE_DATA,
);
- memManager.setTextureMemUse(this, TRANSPARENT_TEXTURE_DATA.byteLength);
+ this.setTextureMemUse(TRANSPARENT_TEXTURE_DATA.byteLength);
} else if ('mipmaps' in textureData.data && textureData.data.mipmaps) {
const {
mipmaps,
@@ -197,7 +193,7 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
glw.texParameteri(glw.TEXTURE_MAG_FILTER, glw.LINEAR);
glw.texParameteri(glw.TEXTURE_MIN_FILTER, glw.LINEAR);
- memManager.setTextureMemUse(this, view.byteLength);
+ this.setTextureMemUse(view.byteLength);
} else {
console.error(
`WebGlCoreCtxTexture.onLoadRequest: Unexpected textureData returned`,
@@ -227,10 +223,10 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
if (!this._nativeCtxTexture) {
return;
}
- const { glw, memManager } = this;
+ const { glw } = this;
glw.deleteTexture(this._nativeCtxTexture);
- memManager.setTextureMemUse(this, 0);
+ this.setTextureMemUse(0);
this._nativeCtxTexture = null;
}
diff --git a/src/core/renderers/webgl/WebGlCoreRenderer.ts b/src/core/renderers/webgl/WebGlCoreRenderer.ts
index 427466e2..13d2e21c 100644
--- a/src/core/renderers/webgl/WebGlCoreRenderer.ts
+++ b/src/core/renderers/webgl/WebGlCoreRenderer.ts
@@ -20,6 +20,7 @@
import { assertTruthy, createWebGLContext, hasOwn } from '../../../utils.js';
import {
CoreRenderer,
+ type BufferInfo,
type CoreRendererOptions,
type QuadOptions,
} from '../CoreRenderer.js';
@@ -50,6 +51,7 @@ import { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
import { RenderTexture } from '../../textures/RenderTexture.js';
import type { CoreNode } from '../../CoreNode.js';
import { WebGlCoreCtxRenderTexture } from './WebGlCoreCtxRenderTexture.js';
+import type { BaseShaderController } from '../../../main-api/ShaderController.js';
import { ImageTexture } from '../../textures/ImageTexture.js';
const WORDS_PER_QUAD = 24;
@@ -68,9 +70,9 @@ export class WebGlCoreRenderer extends CoreRenderer {
system: CoreWebGlSystem;
//// Persistent data
- quadBuffer: ArrayBuffer = new ArrayBuffer(1024 * 1024 * 4);
- fQuadBuffer: Float32Array = new Float32Array(this.quadBuffer);
- uiQuadBuffer: Uint32Array = new Uint32Array(this.quadBuffer);
+ quadBuffer: ArrayBuffer;
+ fQuadBuffer: Float32Array;
+ uiQuadBuffer: Uint32Array;
renderOps: WebGlCoreRenderOp[] = [];
//// Render Op / Buffer Filling State
@@ -80,6 +82,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
activeRttNode: CoreNode | null = null;
//// Default Shader
+ defShaderCtrl: BaseShaderController;
defaultShader: WebGlCoreShader;
quadBufferCollection: BufferCollection;
@@ -88,6 +91,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
*/
defaultTexture: Texture;
+ quadBufferUsage = 0;
/**
* Whether the renderer is currently rendering to a texture.
*/
@@ -95,6 +99,11 @@ export class WebGlCoreRenderer extends CoreRenderer {
constructor(options: WebGlCoreRendererOptions) {
super(options);
+
+ this.quadBuffer = new ArrayBuffer(this.stage.options.quadBufferSize);
+ this.fQuadBuffer = new Float32Array(this.quadBuffer);
+ this.uiQuadBuffer = new Uint32Array(this.quadBuffer);
+
this.mode = 'webgl';
const { canvas, clearColor, bufferMemory } = options;
@@ -102,7 +111,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
this.defaultTexture = new ColorTexture(this.txManager);
// Mark the default texture as ALWAYS renderable
- // This prevents it from ever being garbage collected.
+ // This prevents it from ever being cleaned up.
// Fixes https://github.com/lightning-js/renderer/issues/262
this.defaultTexture.setRenderableOwner(this, true);
@@ -128,7 +137,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
extensions: getWebGlExtensions(this.glw),
};
this.shManager.renderer = this;
- this.defaultShader = this.shManager.loadShader('DefaultShader').shader;
+ this.defShaderCtrl = this.shManager.loadShader('DefaultShader');
+ this.defaultShader = this.defShaderCtrl.shader as WebGlCoreShader;
const quadBuffer = glw.createBuffer();
assertTruthy(quadBuffer);
const stride = 6 * Float32Array.BYTES_PER_ELEMENT;
@@ -235,6 +245,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
tb,
tc,
td,
+ renderCoords,
rtt: renderToTexture,
parentHasRenderTexture,
framebufferDimensions,
@@ -281,7 +292,12 @@ export class WebGlCoreRenderer extends CoreRenderer {
}
const flipX = textureOptions?.flipX ?? false;
- const flipY = textureOptions?.flipY ?? false;
+ let flipY = textureOptions?.flipY ?? false;
+
+ // always flip flipY for render textures
+ if (texture instanceof RenderTexture) {
+ flipY = !flipY;
+ }
let texCoordX1 = 0;
let texCoordY1 = 0;
@@ -333,16 +349,46 @@ export class WebGlCoreRenderer extends CoreRenderer {
[texCoordY1, texCoordY2] = [texCoordY2, texCoordY1];
}
- const { txManager } = this.stage;
- const ctxTexture = txManager.getCtxTexture(texture);
+ const ctxTexture = texture.ctxTexture;
assertTruthy(ctxTexture instanceof WebGlCoreCtxTexture);
const textureIdx = this.addTexture(ctxTexture, bufferIdx);
curRenderOp = this.curRenderOp;
assertTruthy(curRenderOp);
+ if (renderCoords) {
+ const { x1, y1, x2, y2, x3, y3, x4, y4 } = renderCoords;
+ // Upper-Left
+ fQuadBuffer[bufferIdx++] = x1; // vertexX
+ fQuadBuffer[bufferIdx++] = y1; // vertexY
+ fQuadBuffer[bufferIdx++] = texCoordX1; // texCoordX
+ fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
+ uiQuadBuffer[bufferIdx++] = colorTl; // color
+ fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
+
+ // Upper-Right
+ fQuadBuffer[bufferIdx++] = x2;
+ fQuadBuffer[bufferIdx++] = y2;
+ fQuadBuffer[bufferIdx++] = texCoordX2;
+ fQuadBuffer[bufferIdx++] = texCoordY1;
+ uiQuadBuffer[bufferIdx++] = colorTr;
+ fQuadBuffer[bufferIdx++] = textureIdx;
- // render quad advanced
- if (tb !== 0 || tc !== 0) {
+ // Lower-Left
+ fQuadBuffer[bufferIdx++] = x4;
+ fQuadBuffer[bufferIdx++] = y4;
+ fQuadBuffer[bufferIdx++] = texCoordX1;
+ fQuadBuffer[bufferIdx++] = texCoordY2;
+ uiQuadBuffer[bufferIdx++] = colorBl;
+ fQuadBuffer[bufferIdx++] = textureIdx;
+
+ // Lower-Right
+ fQuadBuffer[bufferIdx++] = x3;
+ fQuadBuffer[bufferIdx++] = y3;
+ fQuadBuffer[bufferIdx++] = texCoordX2;
+ fQuadBuffer[bufferIdx++] = texCoordY2;
+ uiQuadBuffer[bufferIdx++] = colorBr;
+ fQuadBuffer[bufferIdx++] = textureIdx;
+ } else if (tb !== 0 || tc !== 0) {
// Upper-Left
fQuadBuffer[bufferIdx++] = tx; // vertexX
fQuadBuffer[bufferIdx++] = ty; // vertexY
@@ -412,7 +458,6 @@ export class WebGlCoreRenderer extends CoreRenderer {
uiQuadBuffer[bufferIdx++] = colorBr;
fQuadBuffer[bufferIdx++] = textureIdx;
}
-
// Update the length of the current render op
curRenderOp.length += WORDS_PER_QUAD;
curRenderOp.numQuads++;
@@ -575,6 +620,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
}
renderOp.draw();
});
+ this.quadBufferUsage = this.curBufferIdx * arr.BYTES_PER_ELEMENT;
}
renderToTexture(node: CoreNode) {
@@ -605,7 +651,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
this.activeRttNode = node;
assertTruthy(node.texture, 'RTT node missing texture');
- const ctxTexture = txManager.getCtxTexture(node.texture);
+ const ctxTexture = node.texture.ctxTexture;
assertTruthy(ctxTexture instanceof WebGlCoreCtxRenderTexture);
this.renderToTextureActive = true;
@@ -655,4 +701,16 @@ export class WebGlCoreRenderer extends CoreRenderer {
}
this.rttNodes.splice(index, 1);
}
+
+ getBufferInfo(): BufferInfo | null {
+ const bufferInfo: BufferInfo = {
+ totalAvailable: this.stage.options.quadBufferSize,
+ totalUsed: this.quadBufferUsage,
+ };
+ return bufferInfo;
+ }
+
+ override getDefShaderCtr(): BaseShaderController {
+ return this.defShaderCtrl;
+ }
}
diff --git a/src/core/renderers/webgl/shaders/DynamicShader.ts b/src/core/renderers/webgl/shaders/DynamicShader.ts
index 288d481c..47bfa2ca 100644
--- a/src/core/renderers/webgl/shaders/DynamicShader.ts
+++ b/src/core/renderers/webgl/shaders/DynamicShader.ts
@@ -16,7 +16,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import type { ExtractProps } from '../../../CoreTextureManager.js';
import type { WebGlCoreRenderer } from '../WebGlCoreRenderer.js';
import {
WebGlCoreShader,
@@ -25,80 +24,85 @@ import {
} from '../WebGlCoreShader.js';
import type { UniformInfo } from '../internal/ShaderUtils.js';
import type { WebGlCoreCtxTexture } from '../WebGlCoreCtxTexture.js';
-import { ShaderEffect } from './effects/ShaderEffect.js';
+import {
+ ShaderEffect,
+ type EffectDescUnion,
+ type ShaderEffectUniform,
+ type ShaderEffectValueMap,
+ type BaseEffectDesc,
+} from './effects/ShaderEffect.js';
import type { EffectMap } from '../../../CoreShaderManager.js';
-import memize from 'memize';
-
-/**
- * Allows the `keyof EffectMap` to be mapped over and form an discriminated
- * union of all the EffectDescs structures individually.
- *
- * @remarks
- * When used like the following:
- * ```
- * MapEffectDescs[]
- * ```
- * The resultant type will be a discriminated union like so:
- * ```
- * (
- * {
- * type: 'radius',
- * props?: {
- * radius?: number | number[];
- * }
- * } |
- * {
- * type: 'border',
- * props?: {
- * width?: number;
- * color?: number;
- * }
- * } |
- * // ...
- * )[]
- * ```
- * Which means TypeScript will now base its type checking on the `type` field
- * and will know exactly what the `props` field should be based on the `type`
- * field.
- */
-type MapEffectDescs = T extends keyof EffectMap
- ? SpecificEffectDesc
- : never;
-
-export type EffectDesc = MapEffectDescs;
+import { assertTruthy } from '../../../../utils.js';
export interface DynamicShaderProps
extends DimensionsShaderProp,
AlphaShaderProp {
- effects?: EffectDesc[];
-}
-
-export interface SpecificEffectDesc<
- FxType extends keyof EffectMap = keyof EffectMap,
-> {
- type: FxType;
- props?: ExtractProps;
+ effects?: EffectDescUnion[];
}
-const effectCache = new Map();
+const effectCache = new Map();
const getResolvedEffect = (
- effects: EffectDesc[] | undefined,
- effectContructors: Partial | undefined,
-): EffectDesc[] => {
+ effects: BaseEffectDesc[],
+ effectContructors: Partial,
+): BaseEffectDesc[] => {
const key = JSON.stringify(effects);
if (effectCache.has(key)) {
return effectCache.get(key)!;
}
+ effects = effects ?? [];
+ const resolvedEffects = [];
+ const effectsLength = effects.length;
+ let i = 0;
+ for (; i < effectsLength; i++) {
+ const { name, type, props } = effects[i] as BaseEffectDesc;
+ const resolvedEffect = {
+ name,
+ type,
+ props: {} as Record,
+ };
+
+ const effectConstructor = effectContructors[type]!;
+ const defaultPropValues = effectConstructor.resolveDefaults(props);
+ const uniforms = effectConstructor.uniforms;
+ const uniformKeys = Object.keys(uniforms);
+ const uniformsLength = uniformKeys.length;
+ let j = 0;
+ for (; j < uniformsLength; j++) {
+ const key = uniformKeys[j]!;
+ const uniform = uniforms[key]!;
+
+ const result: ShaderEffectValueMap = {
+ value: defaultPropValues[key] as ShaderEffectUniform['value'],
+ programValue: undefined,
+ updateOnBind: uniform.updateOnBind || false,
+ hasValidator: uniform.validator !== undefined,
+ hasProgramValueUpdater: uniform.updateProgramValue !== undefined,
+ };
+
+ const validatedValue =
+ (result.hasValidator &&
+ uniform.validator!(defaultPropValues[key], defaultPropValues)) ||
+ defaultPropValues[key];
+
+ if (defaultPropValues[key] !== validatedValue) {
+ result.validatedValue = validatedValue as number | number[];
+ }
- const value = (effects ?? []).map((effect) => ({
- type: effect.type,
- props: effectContructors![effect.type]!.resolveDefaults(
- (effect.props || {}) as any,
- ),
- })) as EffectDesc[];
+ if (result.hasProgramValueUpdater) {
+ uniform.updateProgramValue!(result);
+ }
- effectCache.set(key, value);
- return value;
+ if (result.programValue === undefined) {
+ result.programValue = result.value as number;
+ }
+
+ resolvedEffect.props[key] = result;
+ }
+ resolvedEffects.push(resolvedEffect);
+ }
+
+ effectCache.set(key, resolvedEffects);
+ return resolvedEffects;
};
export class DynamicShader extends WebGlCoreShader {
@@ -130,8 +134,6 @@ export class DynamicShader extends WebGlCoreShader {
this.effects = shader.effects as Array<
InstanceType
>;
-
- this.calculateProps = memize(this.calculateProps.bind(this));
}
override bindTextures(textures: WebGlCoreCtxTexture[]) {
@@ -140,34 +142,29 @@ export class DynamicShader extends WebGlCoreShader {
glw.bindTexture(textures[0]!.ctxTexture);
}
- private calculateProps(effects: EffectDesc[]) {
- const regEffects = this.renderer.shManager.getRegisteredEffects();
- const results: { name: string; value: unknown }[] = [];
- effects?.forEach((eff, index) => {
- const effect = this.effects[index]!;
- const fxClass = regEffects[effect.name as keyof EffectMap]!;
- const props = eff.props ?? {};
- const uniInfo = effect.uniformInfo;
- Object.keys(props).forEach((p) => {
- const fxProp = fxClass.uniforms[p]!;
- const propInfo = uniInfo[p]!;
- let value = fxProp.validator
- ? fxProp.validator(props[p], props)
- : props[p];
- if (Array.isArray(value)) {
- value = new Float32Array(value);
- }
- results.push({ name: propInfo.name, value });
- });
- });
- return results;
- }
-
protected override bindProps(props: Required): void {
- const results = this.calculateProps(props.effects);
- results.forEach((r) => {
- this.setUniform(r.name, r.value);
- });
+ const effects = props.effects;
+ const effectsL = effects.length;
+ let i = 0;
+ for (; i < effectsL; i++) {
+ const effect = effects[i]! as Record;
+ const uniformInfo = this.effects[i]!.uniformInfo;
+ const propKeys = Object.keys(effect.props);
+ const propsLength = propKeys.length;
+ let j = 0;
+ for (; j < propsLength; j++) {
+ const key = propKeys[j]!;
+ const prop = effect.props[key]!;
+ if (prop.updateOnBind === true) {
+ const uniform =
+ this.renderer.shManager.getRegisteredEffects()[
+ effect.type as keyof EffectMap
+ ]?.uniforms[key];
+ uniform?.updateProgramValue!(effect.props[key], props);
+ }
+ this.setUniform(uniformInfo[key]!.name, effect.props[key].programValue);
+ }
+ }
}
override canBatchShaderProps(
@@ -192,7 +189,8 @@ export class DynamicShader extends WebGlCoreShader {
for (const key in effectA.props) {
if (
(effectB.props && !effectB.props[key]) ||
- effectA.props[key] !== effectB.props![key]
+ (effectA.props[key] as ShaderEffectValueMap).value !==
+ (effectB.props[key] as ShaderEffectValueMap).value
) {
return false;
}
@@ -396,8 +394,12 @@ export class DynamicShader extends WebGlCoreShader {
props: DynamicShaderProps,
effectContructors?: Partial,
): Required {
+ assertTruthy(effectContructors);
return {
- effects: getResolvedEffect(props.effects, effectContructors),
+ effects: getResolvedEffect(
+ props.effects ?? [],
+ effectContructors,
+ ) as EffectDescUnion[],
$dimensions: {
width: 0,
height: 0,
diff --git a/src/core/renderers/webgl/shaders/RoundedRectangle.ts b/src/core/renderers/webgl/shaders/RoundedRectangle.ts
index 88423449..f81bfe56 100644
--- a/src/core/renderers/webgl/shaders/RoundedRectangle.ts
+++ b/src/core/renderers/webgl/shaders/RoundedRectangle.ts
@@ -77,7 +77,10 @@ export class RoundedRectangle extends WebGlCoreShader {
}
protected override bindProps(props: Required): void {
- this.setUniform('u_radius', props.radius);
+ const radiusFactor =
+ Math.min(props.$dimensions.width, props.$dimensions.height) /
+ (2.0 * props.radius);
+ this.setUniform('u_radius', props.radius * Math.min(radiusFactor, 1));
}
override canBatchShaderProps(
diff --git a/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.ts b/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.ts
index fe04a72e..b1b27c26 100644
--- a/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.ts
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import { updateShaderEffectColor } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
@@ -69,7 +69,7 @@ export class BorderBottomEffect extends ShaderEffect {
},
color: {
value: 0xffffffff,
- validator: (rgba): number[] => getNormalizedRgbaComponents(rgba),
+ updateProgramValue: updateShaderEffectColor,
method: 'uniform4fv',
type: 'vec4',
},
diff --git a/src/core/renderers/webgl/shaders/effects/BorderEffect.ts b/src/core/renderers/webgl/shaders/effects/BorderEffect.ts
index dceecad0..77a5eb8b 100644
--- a/src/core/renderers/webgl/shaders/effects/BorderEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/BorderEffect.ts
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import { updateShaderEffectColor } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
@@ -69,7 +69,7 @@ export class BorderEffect extends ShaderEffect {
},
color: {
value: 0xffffffff,
- validator: (rgba): number[] => getNormalizedRgbaComponents(rgba),
+ updateProgramValue: updateShaderEffectColor,
method: 'uniform4fv',
type: 'vec4',
},
diff --git a/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.ts b/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.ts
index bbb32c4f..3663230b 100644
--- a/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.ts
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import { updateShaderEffectColor } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
@@ -69,7 +69,7 @@ export class BorderLeftEffect extends ShaderEffect {
},
color: {
value: 0xffffffff,
- validator: (rgba): number[] => getNormalizedRgbaComponents(rgba),
+ updateProgramValue: updateShaderEffectColor,
method: 'uniform4fv',
type: 'vec4',
},
diff --git a/src/core/renderers/webgl/shaders/effects/BorderRightEffect.ts b/src/core/renderers/webgl/shaders/effects/BorderRightEffect.ts
index ebff2224..3a6984f6 100644
--- a/src/core/renderers/webgl/shaders/effects/BorderRightEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/BorderRightEffect.ts
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import { updateShaderEffectColor } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
@@ -69,7 +69,7 @@ export class BorderRightEffect extends ShaderEffect {
},
color: {
value: 0xffffffff,
- validator: (rgba): number[] => getNormalizedRgbaComponents(rgba),
+ updateProgramValue: updateShaderEffectColor,
method: 'uniform4fv',
type: 'vec4',
},
diff --git a/src/core/renderers/webgl/shaders/effects/BorderTopEffect.ts b/src/core/renderers/webgl/shaders/effects/BorderTopEffect.ts
index 22aa33d5..3164e3bf 100644
--- a/src/core/renderers/webgl/shaders/effects/BorderTopEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/BorderTopEffect.ts
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import { updateShaderEffectColor } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
@@ -69,7 +69,7 @@ export class BorderTopEffect extends ShaderEffect {
},
color: {
value: 0xffffffff,
- validator: (rgba): number[] => getNormalizedRgbaComponents(rgba),
+ updateProgramValue: updateShaderEffectColor,
method: 'uniform4fv',
type: 'vec4',
},
diff --git a/src/core/renderers/webgl/shaders/effects/EffectUtils.ts b/src/core/renderers/webgl/shaders/effects/EffectUtils.ts
index ef3dc3a5..62ca70bc 100644
--- a/src/core/renderers/webgl/shaders/effects/EffectUtils.ts
+++ b/src/core/renderers/webgl/shaders/effects/EffectUtils.ts
@@ -1,3 +1,6 @@
+import type { DynamicShaderProps } from '../DynamicShader.js';
+import type { ShaderEffectValueMap } from './ShaderEffect.js';
+
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
@@ -18,9 +21,11 @@
*/
export const colorToFloat32Array = (argb: number) => {
const col = getRgbaComponentsNormalized(argb);
- col[0] *= col[3]!;
- col[1] *= col[3]!;
- col[2] *= col[3]!;
+ /* eslint-disable @typescript-eslint/no-non-null-assertion -- getRgbaComponentsNormalized has a constant array size */
+ col[0]! *= col[3]!;
+ col[1]! *= col[3]!;
+ col[2]! *= col[3]!;
+ /* eslint-enable */
return col;
};
@@ -31,3 +36,124 @@ const getRgbaComponentsNormalized = (argb: number): number[] => {
const a = (argb / 16777216) | 0;
return [r / 255, g / 255, b / 255, a / 255];
};
+
+export const updateShaderEffectColor = (values: ShaderEffectValueMap) => {
+ if (values.programValue === undefined) {
+ values.programValue = new Float32Array(4);
+ }
+ const rgba = values.value as number;
+ const floatArray = values.programValue as Float32Array;
+ floatArray[0] = (rgba >>> 24) / 255;
+ floatArray[1] = ((rgba >>> 16) & 0xff) / 255;
+ floatArray[2] = ((rgba >>> 8) & 0xff) / 255;
+ floatArray[3] = (rgba & 0xff) / 255;
+};
+
+export const updateFloat32ArrayLength2 = (values: ShaderEffectValueMap) => {
+ const validatedValue = (values.validatedValue || values.value) as number[];
+ if (values.programValue instanceof Float32Array) {
+ const floatArray = values.programValue;
+ floatArray[0] = validatedValue[0]!;
+ floatArray[1] = validatedValue[1]!;
+ } else {
+ values.programValue = new Float32Array(validatedValue);
+ }
+};
+
+export const updateFloat32ArrayLength4 = (values: ShaderEffectValueMap) => {
+ const validatedValue = (values.validatedValue || values.value) as number[];
+ if (values.programValue instanceof Float32Array) {
+ const floatArray = values.programValue;
+ floatArray[0] = validatedValue[0]!;
+ floatArray[1] = validatedValue[1]!;
+ floatArray[2] = validatedValue[1]!;
+ floatArray[3] = validatedValue[1]!;
+ } else {
+ values.programValue = new Float32Array(validatedValue);
+ }
+};
+
+export const updateFloat32ArrayLengthN = (values: ShaderEffectValueMap) => {
+ const validatedValue = (values.validatedValue || values.value) as number[];
+ if (values.programValue instanceof Float32Array) {
+ const len = validatedValue.length;
+ const programValue = values.programValue;
+ for (let i = 0; i < len; i++) {
+ programValue[i] = validatedValue[i]!;
+ }
+ } else {
+ values.programValue = new Float32Array(validatedValue);
+ }
+};
+
+export const validateArrayLength4 = (value: number | number[]): number[] => {
+ const isArray = Array.isArray(value);
+ if (!isArray) {
+ return [value, value, value, value];
+ } else if (isArray && value.length === 4) {
+ return value;
+ } else if (isArray && value.length === 2) {
+ return [value[0]!, value[1]!, value[0]!, value[1]!];
+ } else if (isArray && value.length === 3) {
+ return [value[0]!, value[1]!, value[2]!, value[0]!];
+ }
+ return [value[0]!, value[0]!, value[0]!, value[0]!];
+};
+
+export const updateWebSafeRadius = (
+ values: ShaderEffectValueMap,
+ shaderProps?: DynamicShaderProps,
+) => {
+ if (values.programValue === undefined) {
+ values.programValue = new Float32Array(4);
+ }
+ const programValue = values.programValue as Float32Array;
+ const validatedValue = (values.validatedValue || values.value) as number[];
+ if (shaderProps === undefined && values.$dimensions === undefined) {
+ programValue[0] = validatedValue[0]!;
+ programValue[1] = validatedValue[1]!;
+ programValue[2] = validatedValue[2]!;
+ programValue[3] = validatedValue[3]!;
+ return;
+ }
+
+ let storedDimensions = values.$dimensions;
+ if (shaderProps !== undefined) {
+ const { $dimensions } = shaderProps;
+ if (
+ storedDimensions !== undefined &&
+ (storedDimensions.width === $dimensions!.width ||
+ storedDimensions.height === $dimensions!.height)
+ ) {
+ return;
+ }
+ if (storedDimensions === undefined) {
+ storedDimensions = {
+ width: $dimensions?.width as number,
+ height: $dimensions?.height as number,
+ };
+ values.$dimensions = storedDimensions;
+ }
+ }
+
+ const { width, height } = storedDimensions!;
+ const [r0, r1, r2, r3] = validatedValue;
+ const factor = Math.min(
+ Math.min(
+ Math.min(
+ width / Math.max(width, r0! + r1!),
+ width / Math.max(width, r2! + r3!),
+ ),
+ Math.min(
+ height / Math.max(height, r0! + r2!),
+ height / Math.max(height, r1! + r3!),
+ ),
+ ),
+ 1,
+ );
+
+ programValue[0] = r0! * factor;
+ programValue[1] = r1! * factor;
+ programValue[2] = r2! * factor;
+ programValue[3] = r3! * factor;
+};
diff --git a/src/core/renderers/webgl/shaders/effects/FadeOutEffect.ts b/src/core/renderers/webgl/shaders/effects/FadeOutEffect.ts
index 16a56ef6..55b48af9 100644
--- a/src/core/renderers/webgl/shaders/effects/FadeOutEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/FadeOutEffect.ts
@@ -16,10 +16,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import {
+ updateFloat32ArrayLength4,
+ validateArrayLength4,
+} from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
type ShaderEffectUniforms,
+ type ShaderEffectValueMap,
} from './ShaderEffect.js';
/**
@@ -63,21 +68,8 @@ export class FadeOutEffect extends ShaderEffect {
value: 0,
method: 'uniform4fv',
type: 'vec4',
- validator: (value: number | number[]) => {
- let r = value;
- if (Array.isArray(r)) {
- if (r.length === 2) {
- r = [r[0], r[1], r[0], r[1]] as number[];
- } else if (r.length === 3) {
- r = [r[0], r[1], r[2], r[0]] as number[];
- } else if (r.length !== 4) {
- r = [r[0], r[0], r[0], r[0]] as number[];
- }
- } else if (typeof r === 'number') {
- r = [r, r, r, r];
- }
- return r;
- },
+ validator: validateArrayLength4,
+ updateProgramValue: updateFloat32ArrayLength4,
},
};
diff --git a/src/core/renderers/webgl/shaders/effects/GlitchEffect.ts b/src/core/renderers/webgl/shaders/effects/GlitchEffect.ts
index 2ef2a7c7..7cf4d4e3 100644
--- a/src/core/renderers/webgl/shaders/effects/GlitchEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/GlitchEffect.ts
@@ -84,8 +84,11 @@ export class GlitchEffect extends ShaderEffect {
time: {
value: 0,
method: 'uniform1f',
- validator: (value: number) => {
- return (Date.now() - value) % 1000;
+ updateOnBind: true,
+ updateProgramValue: (values) => {
+ const value = (values.value =
+ (Date.now() - (values.value as number)) % 1000);
+ values.programValue = value;
},
type: 'float',
},
diff --git a/src/core/renderers/webgl/shaders/effects/HolePunchEffect.ts b/src/core/renderers/webgl/shaders/effects/HolePunchEffect.ts
index dab1eed0..12fcb994 100644
--- a/src/core/renderers/webgl/shaders/effects/HolePunchEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/HolePunchEffect.ts
@@ -16,10 +16,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import type { DynamicShaderProps } from '../DynamicShader.js';
+import { updateWebSafeRadius, validateArrayLength4 } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
type ShaderEffectUniforms,
+ type ShaderEffectValueMap,
} from './ShaderEffect.js';
/**
@@ -103,21 +106,9 @@ export class HolePunchEffect extends ShaderEffect {
value: 0,
method: 'uniform4fv',
type: 'vec4',
- validator: (value: number | number[]) => {
- let r = value;
- if (Array.isArray(r)) {
- if (r.length === 2) {
- r = [r[0], r[1], r[0], r[1]] as number[];
- } else if (r.length === 3) {
- r = [r[0], r[1], r[2], r[0]] as number[];
- } else if (r.length !== 4) {
- r = [r[0], r[0], r[0], r[0]] as number[];
- }
- } else if (typeof r === 'number') {
- r = [r, r, r, r];
- }
- return r;
- },
+ updateOnBind: true,
+ validator: validateArrayLength4,
+ updateProgramValue: updateWebSafeRadius,
},
};
diff --git a/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.ts b/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.ts
index 3077ba58..fc08e7e8 100644
--- a/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.ts
@@ -17,6 +17,7 @@
* limitations under the License.
*/
import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import { updateFloat32ArrayLengthN } from './EffectUtils.js';
import {
type DefaultEffectProps,
ShaderEffect,
@@ -94,9 +95,12 @@ export class LinearGradientEffect extends ShaderEffect {
colors: {
value: 0xffffffff,
validator: (rgbas: number[]): number[] => {
- const cols = rgbas.map((rgbas) => getNormalizedRgbaComponents(rgbas));
- return cols.reduce((acc, val) => acc.concat(val), [] as number[]);
+ return rgbas.reduce(
+ (acc, val) => acc.concat(getNormalizedRgbaComponents(val)),
+ [] as number[],
+ );
},
+ updateProgramValue: updateFloat32ArrayLengthN,
size: (props: LinearGradientEffectProps) => props.colors!.length,
method: 'uniform4fv',
type: 'vec4',
diff --git a/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.ts b/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.ts
index d08d415f..5ee2eff6 100644
--- a/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.ts
@@ -17,6 +17,10 @@
* limitations under the License.
*/
import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import {
+ updateFloat32ArrayLength2,
+ updateFloat32ArrayLengthN,
+} from './EffectUtils.js';
import {
type DefaultEffectProps,
ShaderEffect,
@@ -105,15 +109,19 @@ export class RadialGradientEffect extends ShaderEffect {
},
pivot: {
value: [0.5, 0.5],
+ updateProgramValue: updateFloat32ArrayLength2,
method: 'uniform2fv',
type: 'vec2',
},
colors: {
value: 0xffffffff,
validator: (rgbas: number[]): number[] => {
- const cols = rgbas.map((rgbas) => getNormalizedRgbaComponents(rgbas));
- return cols.reduce((acc, val) => acc.concat(val), [] as number[]);
+ return rgbas.reduce(
+ (acc, val) => acc.concat(getNormalizedRgbaComponents(val)),
+ [] as number[],
+ );
},
+ updateProgramValue: updateFloat32ArrayLengthN,
size: (props: RadialGradientEffectProps) => props.colors!.length,
method: 'uniform4fv',
type: 'vec4',
diff --git a/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.ts b/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.ts
index 7c4c3284..238b7e15 100644
--- a/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.ts
@@ -17,6 +17,7 @@
* limitations under the License.
*/
import { getNormalizedRgbaComponents } from '../../../../lib/utils.js';
+import { updateShaderEffectColor } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
@@ -132,7 +133,7 @@ export class RadialProgressEffect extends ShaderEffect {
},
color: {
value: 0xffffffff,
- validator: (rgba): number[] => getNormalizedRgbaComponents(rgba),
+ updateProgramValue: updateShaderEffectColor,
method: 'uniform4fv',
type: 'vec4',
},
diff --git a/src/core/renderers/webgl/shaders/effects/RadiusEffect.ts b/src/core/renderers/webgl/shaders/effects/RadiusEffect.ts
index f2c86a4e..40e9b212 100644
--- a/src/core/renderers/webgl/shaders/effects/RadiusEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/RadiusEffect.ts
@@ -16,10 +16,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import type { DynamicShaderProps } from '../DynamicShader.js';
+import { updateWebSafeRadius, validateArrayLength4 } from './EffectUtils.js';
import {
ShaderEffect,
type DefaultEffectProps,
type ShaderEffectUniforms,
+ type ShaderEffectValueMap,
} from './ShaderEffect.js';
/**
@@ -65,21 +68,9 @@ export class RadiusEffect extends ShaderEffect {
value: 0,
method: 'uniform4fv',
type: 'vec4',
- validator: (value: number | number[]) => {
- let r = value;
- if (Array.isArray(r)) {
- if (r.length === 2) {
- r = [r[0], r[1], r[0], r[1]] as number[];
- } else if (r.length === 3) {
- r = [r[0], r[1], r[2], r[0]] as number[];
- } else if (r.length !== 4) {
- r = [r[0], r[0], r[0], r[0]] as number[];
- }
- } else if (typeof r === 'number') {
- r = [r, r, r, r];
- }
- return r;
- },
+ updateOnBind: true,
+ validator: validateArrayLength4,
+ updateProgramValue: updateWebSafeRadius,
},
};
diff --git a/src/core/renderers/webgl/shaders/effects/ShaderEffect.ts b/src/core/renderers/webgl/shaders/effects/ShaderEffect.ts
index 910275cb..8cb18fc0 100644
--- a/src/core/renderers/webgl/shaders/effects/ShaderEffect.ts
+++ b/src/core/renderers/webgl/shaders/effects/ShaderEffect.ts
@@ -1,20 +1,100 @@
+import type { EffectMap } from '../../../../CoreShaderManager.js';
+import type { ExtractProps } from '../../../../CoreTextureManager.js';
+import type {
+ AlphaShaderProp,
+ DimensionsShaderProp,
+} from '../../WebGlCoreShader.js';
import type {
UniformInfo,
UniformMethodMap,
} from '../../internal/ShaderUtils.js';
+export interface BaseEffectDesc {
+ name?: string;
+ type: keyof EffectMap;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ props: Record;
+}
+
+export interface EffectDesc<
+ T extends { name?: string; type: keyof EffectMap } = {
+ name?: string;
+ type: keyof EffectMap;
+ },
+> extends BaseEffectDesc {
+ name?: T['name'];
+ type: T['type'];
+ props: ExtractProps;
+}
+
+/**
+ * Allows the `keyof EffectMap` to be mapped over and form an discriminated
+ * union of all the EffectDescs structures individually.
+ *
+ * @remarks
+ * When used like the following:
+ * ```
+ * MapEffectDescs[]
+ * ```
+ * The resultant type will be a discriminated union like so:
+ * ```
+ * (
+ * {
+ * name: 'effect1',
+ * type: 'radius',
+ * props?: {
+ * radius?: number | number[];
+ * }
+ * } |
+ * {
+ * name: 'effect2',
+ * type: 'border',
+ * props?: {
+ * width?: number;
+ * color?: number;
+ * }
+ * } |
+ * // ...
+ * )[]
+ * ```
+ * Which means TypeScript will now base its type checking on the `type` field
+ * and will know exactly what the `props` field should be based on the `type`
+ * field.
+ */
+type MapEffectDescs = T extends keyof EffectMap
+ ? EffectDesc<{ type: T; name: string }>
+ : never;
+
+export type EffectDescUnion = MapEffectDescs;
+
export interface ShaderEffectUniform {
value: number | number[] | boolean | string;
type: string;
method: keyof UniformMethodMap;
name?: string;
size?: (value: Record) => number;
+ updateOnBind?: boolean;
+ updateProgramValue?: (
+ programValues: ShaderEffectValueMap,
+ shaderProps?: Record,
+ ) => void;
validator?: (
value: any,
props: Record,
) => number | number[] | number[][];
}
+export interface ShaderEffectValueMap
+ extends DimensionsShaderProp,
+ AlphaShaderProp {
+ value: ShaderEffectUniform['value'];
+ programValue: number | Float32Array | undefined;
+ hasValidator: boolean;
+ hasProgramValueUpdater: boolean;
+ updateOnBind: boolean;
+ validatedValue?: number | number[];
+}
+
export interface ShaderEffectUniforms {
[key: string]: ShaderEffectUniform;
}
diff --git a/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts b/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts
index 3a014b12..237540c1 100644
--- a/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts
+++ b/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts
@@ -25,7 +25,6 @@ import { ImageTexture } from '../../../textures/ImageTexture.js';
import {
TrFontFace,
type NormalizedFontMetrics,
- type TrFontFaceDescriptors,
type TrFontFaceOptions,
} from '../TrFontFace.js';
import type { FontShaper } from './internal/FontShaper.js';
@@ -77,25 +76,25 @@ export class SdfTrFontFace<
'SDF Font Faces can only be used with the WebGL Renderer',
);
- this.texture = stage.txManager.loadTexture(
- 'ImageTexture',
- {
- src: atlasUrl,
- // IMPORTANT: The SDF shader requires the alpha channel to NOT be
- // premultiplied on the atlas texture. If it is premultiplied, the
- // rendering of SDF glyphs (especially single-channel SDF fonts) will
- // be very jagged.
- premultiplyAlpha: false,
- },
- {
- preload: true,
- },
- );
+ // Load image
+ this.texture = stage.txManager.loadTexture('ImageTexture', {
+ src: atlasUrl,
+ // IMPORTANT: The SDF shader requires the alpha channel to NOT be
+ // premultiplied on the atlas texture. If it is premultiplied, the
+ // rendering of SDF glyphs (especially single-channel SDF fonts) will
+ // be very jagged.
+ premultiplyAlpha: false,
+ });
this.texture.on('loaded', () => {
this.checkLoaded();
+ // Make sure we mark the stage for a re-render (in case the font's texture was freed and reloaded)
+ stage.requestRender();
});
+ // Pre-load it
+ this.texture.ctxTexture.load();
+
// Set this.data to the fetched data from dataUrl
fetch(atlasDataUrl)
.then(async (response) => {
diff --git a/src/core/text-rendering/font-face-types/TrFontFace.ts b/src/core/text-rendering/font-face-types/TrFontFace.ts
index d22fb072..307b0362 100644
--- a/src/core/text-rendering/font-face-types/TrFontFace.ts
+++ b/src/core/text-rendering/font-face-types/TrFontFace.ts
@@ -61,7 +61,6 @@ export interface TrFontFaceDescriptors {
unicodeRange?: string;
display?: FontDisplay;
featureSettings?: string;
- variant?: string;
}
export interface FontMetrics {
@@ -182,7 +181,6 @@ export class TrFontFace extends EventEmitter {
: descriptors.weight,
stretch: descriptors.stretch,
unicodeRange: descriptors.unicodeRange,
- variant: descriptors.variant,
featureSettings: descriptors.featureSettings,
display: descriptors.display,
};
diff --git a/src/core/text-rendering/font-face-types/WebTrFontFace.ts b/src/core/text-rendering/font-face-types/WebTrFontFace.ts
index a82d5ba8..ab745eaf 100644
--- a/src/core/text-rendering/font-face-types/WebTrFontFace.ts
+++ b/src/core/text-rendering/font-face-types/WebTrFontFace.ts
@@ -57,7 +57,6 @@ export class WebTrFontFace extends TrFontFace {
: determinedDescriptors.weight,
stretch: determinedDescriptors.stretch,
unicodeRange: determinedDescriptors.unicodeRange,
- variant: determinedDescriptors.variant,
featureSettings: determinedDescriptors.featureSettings,
display: determinedDescriptors.display,
};
diff --git a/src/core/text-rendering/renderers/CanvasTextRenderer.ts b/src/core/text-rendering/renderers/CanvasTextRenderer.ts
index dbe99311..b6c15979 100644
--- a/src/core/text-rendering/renderers/CanvasTextRenderer.ts
+++ b/src/core/text-rendering/renderers/CanvasTextRenderer.ts
@@ -18,19 +18,13 @@
*/
import { EventEmitter } from '../../../common/EventEmitter.js';
-import { assertTruthy, mergeColorAlphaPremultiplied } from '../../../utils.js';
+import { assertTruthy } from '../../../utils.js';
+import type { CoreNode } from '../../CoreNode.js';
+import type { CoreTextNode } from '../../CoreTextNode.js';
import type { Stage } from '../../Stage.js';
-import type { Matrix3d } from '../../lib/Matrix3d.js';
import {
- intersectRect,
- type Bound,
- intersectBound,
getNormalizedRgbaComponents,
- type Rect,
getNormalizedAlphaComponent,
- type BoundWithValid,
- createBound,
- type RectWithValid,
} from '../../lib/utils.js';
import type { ImageTexture } from '../../textures/ImageTexture.js';
import { TrFontManager, type FontFamilyMap } from '../TrFontManager.js';
@@ -62,13 +56,6 @@ declare module './TextRenderer.js' {
}
}
-interface CanvasPageInfo {
- texture: ImageTexture | undefined;
- lineNumStart: number;
- lineNumEnd: number;
- valid: boolean;
-}
-
function getFontCssString(props: TrProps): string {
const { fontFamily, fontStyle, fontWeight, fontStretch, fontSize } = props;
return [fontStyle, fontWeight, fontStretch, `${fontSize}px`, fontFamily].join(
@@ -77,9 +64,8 @@ function getFontCssString(props: TrProps): string {
}
export interface CanvasTextRendererState extends TextRendererState {
+ node: CoreTextNode;
props: TrProps;
-
- fontFaceLoadedHandler: (() => void) | undefined;
fontInfo:
| {
fontFace: WebTrFontFace;
@@ -87,28 +73,16 @@ export interface CanvasTextRendererState extends TextRendererState {
loaded: boolean;
}
| undefined;
- canvasPages: [CanvasPageInfo, CanvasPageInfo, CanvasPageInfo] | undefined;
+ textureNode: CoreNode | undefined;
lightning2TextRenderer: LightningTextTextureRenderer;
renderInfo: RenderInfo | undefined;
- renderWindow: Bound | undefined;
- visibleWindow: BoundWithValid;
}
-/**
- * Ephemeral bounds object used for intersection calculations
- *
- * @remarks
- * Used to avoid creating a new object every time we need to intersect
- * element bounds.
- */
-const tmpElementBounds = createBound(0, 0, 0, 0);
-
export class CanvasTextRenderer extends TextRenderer {
protected canvas: OffscreenCanvas | HTMLCanvasElement;
protected context:
| OffscreenCanvasRenderingContext2D
| CanvasRenderingContext2D;
- private rendererBounds: Bound;
/**
* Font family map used to store web font faces that were added to the
* canvas text renderer.
@@ -124,25 +98,21 @@ export class CanvasTextRenderer extends TextRenderer {
this.canvas = document.createElement('canvas');
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
- let context = this.canvas.getContext('2d') as
- | OffscreenCanvasRenderingContext2D
- | CanvasRenderingContext2D
- | null;
+ let context = this.canvas.getContext('2d', {
+ willReadFrequently: true,
+ }) as OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D | null;
if (!context) {
// A browser may appear to support OffscreenCanvas but not actually support the Canvas '2d' context
// Here we try getting the context again after falling back to an HTMLCanvasElement.
// See: https://github.com/lightning-js/renderer/issues/26#issuecomment-1750438486
this.canvas = document.createElement('canvas');
- context = this.canvas.getContext('2d');
+ context = this.canvas.getContext('2d', {
+ willReadFrequently: true,
+ });
}
assertTruthy(context);
this.context = context;
- this.rendererBounds = {
- x1: 0,
- y1: 0,
- x2: this.stage.options.appWidth,
- y2: this.stage.options.appHeight,
- };
+
// Install the default 'san-serif' font face
this.addFontFace(
new WebTrFontFace({
@@ -197,11 +167,9 @@ export class CanvasTextRenderer extends TextRenderer {
},
x: (state, value) => {
state.props.x = value;
- this.invalidateVisibleWindowCache(state);
},
y: (state, value) => {
state.props.y = value;
- this.invalidateVisibleWindowCache(state);
},
contain: (state, value) => {
state.props.contain = value;
@@ -252,9 +220,6 @@ export class CanvasTextRenderer extends TextRenderer {
state.props.overflowSuffix = value;
this.invalidateLayoutCache(state);
},
- // debug: (state, value) => {
- // state.props.debug = value;
- // },
};
}
@@ -296,31 +261,26 @@ export class CanvasTextRenderer extends TextRenderer {
faceSet.add(fontFace);
}
- override createState(props: TrProps): CanvasTextRendererState {
+ override createState(
+ props: TrProps,
+ node: CoreTextNode,
+ ): CanvasTextRendererState {
return {
+ node,
props,
status: 'initialState',
updateScheduled: false,
emitter: new EventEmitter(),
- canvasPages: undefined,
+ textureNode: undefined,
lightning2TextRenderer: new LightningTextTextureRenderer(
this.canvas,
this.context,
),
- renderWindow: undefined,
- visibleWindow: {
- x1: 0,
- y1: 0,
- x2: 0,
- y2: 0,
- valid: false,
- },
renderInfo: undefined,
forceFullLayoutCalc: false,
textW: 0,
textH: 0,
fontInfo: undefined,
- fontFaceLoadedHandler: undefined,
isRenderable: false,
debugData: {
updateCount: 0,
@@ -338,30 +298,20 @@ export class CanvasTextRenderer extends TextRenderer {
// On the first update call we need to set the status to loading
if (state.status === 'initialState') {
this.setStatus(state, 'loading');
+ // check if we're on screen
+ // if (this.isValidOnScreen(state) === true) {
+ // this.setStatus(state, 'loading');
+ // }
+ }
+
+ if (state.status === 'loaded') {
+ // If we're loaded, we don't need to do anything
+ return;
}
// If fontInfo is invalid, we need to establish it
if (!state.fontInfo) {
- const cssString = getFontCssString(state.props);
- const trFontFace = TrFontManager.resolveFontFace(
- this.fontFamilyArray,
- state.props,
- ) as WebTrFontFace | undefined;
- assertTruthy(trFontFace, `Could not resolve font face for ${cssString}`);
- state.fontInfo = {
- fontFace: trFontFace,
- cssString: cssString,
- // TODO: For efficiency we would use this here but it's not reliable on WPE -> document.fonts.check(cssString),
- loaded: false,
- };
- // If font is not loaded, set up a handler to update the font info when the font loads
- if (!state.fontInfo.loaded) {
- globalFontSet
- .load(cssString)
- .then(this.onFontLoaded.bind(this, state, cssString))
- .catch(this.onFontLoadError.bind(this, state, cssString));
- return;
- }
+ return this.loadFont(state);
}
// If we're waiting for a font face to load, don't render anything
@@ -370,402 +320,145 @@ export class CanvasTextRenderer extends TextRenderer {
}
if (!state.renderInfo) {
- state.lightning2TextRenderer.settings = {
- text: state.props.text,
- textAlign: state.props.textAlign,
- fontFamily: state.props.fontFamily,
- trFontFace: state.fontInfo.fontFace,
- fontSize: state.props.fontSize,
- fontStyle: [
- state.props.fontStretch,
- state.props.fontStyle,
- state.props.fontWeight,
- ].join(' '),
- textColor: getNormalizedRgbaComponents(state.props.color),
- offsetY: state.props.offsetY,
- wordWrap: state.props.contain !== 'none',
- wordWrapWidth:
- state.props.contain === 'none' ? undefined : state.props.width,
- letterSpacing: state.props.letterSpacing,
- lineHeight: state.props.lineHeight ?? null,
- maxLines: state.props.maxLines,
- maxHeight:
- state.props.contain === 'both'
- ? state.props.height - state.props.offsetY
- : null,
- textBaseline: state.props.textBaseline,
- verticalAlign: state.props.verticalAlign,
- overflowSuffix: state.props.overflowSuffix,
- w: state.props.contain !== 'none' ? state.props.width : undefined,
- };
- // const renderInfoCalculateTime = performance.now();
- state.renderInfo = state.lightning2TextRenderer.calculateRenderInfo();
- // console.log(
- // 'Render info calculated in',
- // performance.now() - renderInfoCalculateTime,
- // 'ms',
- // );
+ state.renderInfo = this.calculateRenderInfo(state);
state.textH = state.renderInfo.lineHeight * state.renderInfo.lines.length;
state.textW = state.renderInfo.width;
-
- // Invalidate renderWindow because the renderInfo changed
- state.renderWindow = undefined;
+ this.renderSingleCanvasPage(state);
}
- const { x, y, width, height, scrollY, contain } = state.props;
- const { visibleWindow } = state;
- let { renderWindow, canvasPages } = state;
-
- if (!visibleWindow.valid) {
- // Figure out whats actually in the bounds of the renderer/canvas (visibleWindow)
- const elementBounds = createBound(
- x,
- y,
- contain !== 'none' ? x + width : Infinity,
- contain === 'both' ? y + height : Infinity,
- tmpElementBounds,
- );
- /**
- * Area that is visible on the screen.
- */
- intersectBound(this.rendererBounds, elementBounds, visibleWindow);
- visibleWindow.valid = true;
- }
+ // handle scrollable text !!!
+ // if (state.isScrollable === true) {
+ // return this.renderScrollableCanvasPages(state);
+ // }
- const visibleWindowHeight = visibleWindow.y2 - visibleWindow.y1;
+ // handle single page text
+ }
- const maxLinesPerCanvasPage = Math.ceil(
- visibleWindowHeight / state.renderInfo.lineHeight,
- );
+ renderSingleCanvasPage(state: CanvasTextRendererState): void {
+ assertTruthy(state.renderInfo);
+ const node = state.node;
- if (visibleWindowHeight === 0) {
- // Nothing to render. Clear any canvasPages and existing renderWindow
- // Return early.
- canvasPages = undefined;
- renderWindow = undefined;
- this.setStatus(state, 'loaded');
- return;
- } else if (renderWindow && canvasPages) {
- // Return early if we're still viewing inside the established render window
- // No need to re-render what we've already rendered
- const renderWindowScreenX1 = x + renderWindow.x1;
- const renderWindowScreenY1 = y - scrollY + renderWindow.y1;
- const renderWindowScreenX2 = x + renderWindow.x2;
- const renderWindowScreenY2 = y - scrollY + renderWindow.y2;
-
- if (
- renderWindowScreenX1 <= visibleWindow.x1 &&
- renderWindowScreenX2 >= visibleWindow.x2 &&
- renderWindowScreenY1 <= visibleWindow.y1 &&
- renderWindowScreenY2 >= visibleWindow.y2
+ const texture = this.stage.txManager.loadTexture('ImageTexture', {
+ src: function (
+ this: CanvasTextRenderer,
+ lightning2TextRenderer: LightningTextTextureRenderer,
+ renderInfo: RenderInfo,
) {
- this.setStatus(state, 'loaded');
- return;
- }
- if (renderWindowScreenY2 < visibleWindow.y2) {
- // We've scrolled up, so we need to render the next page
- renderWindow.y1 += maxLinesPerCanvasPage * state.renderInfo.lineHeight;
- renderWindow.y2 += maxLinesPerCanvasPage * state.renderInfo.lineHeight;
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- canvasPages.push(canvasPages.shift()!);
- canvasPages[2].lineNumStart =
- canvasPages[1].lineNumStart + maxLinesPerCanvasPage;
- canvasPages[2].lineNumEnd =
- canvasPages[2].lineNumStart + maxLinesPerCanvasPage;
- canvasPages[2].valid = false;
- } else if (renderWindowScreenY1 > visibleWindow.y1) {
- // We've scrolled down, so we need to render the previous page
- renderWindow.y1 -= maxLinesPerCanvasPage * state.renderInfo.lineHeight;
- renderWindow.y2 -= maxLinesPerCanvasPage * state.renderInfo.lineHeight;
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- canvasPages.unshift(canvasPages.pop()!);
- canvasPages[0].lineNumStart =
- canvasPages[1].lineNumStart - maxLinesPerCanvasPage;
- canvasPages[0].lineNumEnd =
- canvasPages[0].lineNumStart + maxLinesPerCanvasPage;
- canvasPages[0].valid = false;
- }
- } else {
- const pageHeight = state.renderInfo.lineHeight * maxLinesPerCanvasPage;
- const page1Block = Math.ceil(scrollY / pageHeight);
- const page1LineStart = page1Block * maxLinesPerCanvasPage;
- const page0LineStart = page1LineStart - maxLinesPerCanvasPage;
- const page2LineStart = page1LineStart + maxLinesPerCanvasPage;
-
- // We haven't rendered anything yet, so we need to render the first page
- // If canvasPages already exist, let's re-use the textures
- canvasPages = [
- {
- texture: canvasPages?.[0].texture,
- lineNumStart: page0LineStart,
- lineNumEnd: page0LineStart + maxLinesPerCanvasPage,
- valid: false,
- },
- {
- texture: canvasPages?.[1].texture,
- lineNumStart: page1LineStart,
- lineNumEnd: page1LineStart + maxLinesPerCanvasPage,
- valid: false,
- },
- {
- texture: canvasPages?.[2].texture,
- lineNumStart: page2LineStart,
- lineNumEnd: page2LineStart + maxLinesPerCanvasPage,
- valid: false,
- },
- ];
- state.canvasPages = canvasPages;
-
- const scrollYNearestPage = page1Block * pageHeight;
-
- renderWindow = {
- x1: 0,
- y1: scrollYNearestPage - pageHeight,
- x2: width,
- y2: scrollYNearestPage + pageHeight * 2,
- };
- }
-
- state.renderWindow = renderWindow;
-
- const pageDrawTime = performance.now();
- for (const pageInfo of canvasPages) {
- if (pageInfo.valid) continue;
- if (pageInfo.lineNumStart < 0) {
- pageInfo.texture?.setRenderableOwner(state, false);
- pageInfo.texture = this.stage.txManager.loadTexture('ImageTexture', {
- src: '',
+ // load the canvas texture
+ assertTruthy(renderInfo);
+ lightning2TextRenderer.draw(renderInfo, {
+ lines: renderInfo.lines,
+ lineWidths: renderInfo.lineWidths,
});
- pageInfo.texture.setRenderableOwner(state, state.isRenderable);
- pageInfo.valid = true;
- continue;
- }
- state.lightning2TextRenderer.draw(state.renderInfo, {
- lines: state.renderInfo.lines.slice(
- pageInfo.lineNumStart,
- pageInfo.lineNumEnd,
- ),
- lineWidths: state.renderInfo.lineWidths.slice(
- pageInfo.lineNumStart,
- pageInfo.lineNumEnd,
- ),
- });
- if (!(this.canvas.width === 0 || this.canvas.height === 0)) {
- pageInfo.texture?.setRenderableOwner(state, false);
- pageInfo.texture = this.stage.txManager.loadTexture(
- 'ImageTexture',
- {
- src: this.context.getImageData(
- 0,
- 0,
- this.canvas.width,
- this.canvas.height,
- ),
- },
- {
- preload: true,
- },
+ if (this.canvas.width === 0 || this.canvas.height === 0) {
+ return null;
+ }
+ return this.context.getImageData(
+ 0,
+ 0,
+ this.canvas.width,
+ this.canvas.height,
);
- pageInfo.texture.setRenderableOwner(state, state.isRenderable);
- }
- pageInfo.valid = true;
+ }.bind(this, state.lightning2TextRenderer, state.renderInfo),
+ });
+ if (state.textureNode) {
+ // Use the existing texture node
+ state.textureNode.texture = texture;
+ } else {
+ // Create a new texture node
+ const textureNode = this.stage.createNode({
+ parent: node,
+ texture,
+ autosize: true,
+ // The alpha channel of the color is ignored when rasterizing the text
+ // texture so we need to pass it directly to the texture node.
+ alpha: getNormalizedAlphaComponent(state.props.color),
+ });
+ state.textureNode = textureNode;
}
- // console.log('pageDrawTime', performance.now() - pageDrawTime, 'ms');
- // Report final status
this.setStatus(state, 'loaded');
}
- override renderQuads(
- state: CanvasTextRendererState,
- transform: Matrix3d,
- clippingRect: RectWithValid,
- alpha: number,
- ): void {
- const { stage } = this;
-
- const { canvasPages, textW = 0, textH = 0, renderWindow } = state;
-
- if (!canvasPages || !renderWindow) return;
-
- const { x, y, scrollY, contain, width, height /*, debug*/ } = state.props;
-
- const elementRect = {
- x: x,
- y: y,
- width: contain !== 'none' ? width : textW,
- height: contain === 'both' ? height : textH,
+ loadFont = (state: CanvasTextRendererState): void => {
+ const cssString = getFontCssString(state.props);
+ const trFontFace = TrFontManager.resolveFontFace(
+ this.fontFamilyArray,
+ state.props,
+ ) as WebTrFontFace | undefined;
+ assertTruthy(trFontFace, `Could not resolve font face for ${cssString}`);
+ state.fontInfo = {
+ fontFace: trFontFace,
+ cssString: cssString,
+ // TODO: For efficiency we would use this here but it's not reliable on WPE -> document.fonts.check(cssString),
+ loaded: false,
};
-
- const visibleRect = intersectRect(
- {
- x: 0,
- y: 0,
- width: stage.options.appWidth,
- height: stage.options.appHeight,
- },
- elementRect,
- );
-
- // if (!debug.disableScissor) {
- // renderer.enableScissor(
- // visibleRect.x,
- // visibleRect.y,
- // visibleRect.w,
- // visibleRect.h,
- // );
- // }
-
- assertTruthy(canvasPages, 'canvasPages is not defined');
- assertTruthy(renderWindow, 'renderWindow is not defined');
-
- const renderWindowHeight = renderWindow.y2 - renderWindow.y1;
- const pageSize = renderWindowHeight / 3.0;
-
- const { zIndex, color } = state.props;
-
- // Color alpha of text is not properly rendered to the Canvas texture, so we
- // need to apply it here.
- const combinedAlpha = alpha * getNormalizedAlphaComponent(color);
- const quadColor = mergeColorAlphaPremultiplied(0xffffffff, combinedAlpha);
- if (canvasPages[0].valid) {
- this.stage.renderer.addQuad({
- alpha: combinedAlpha,
- clippingRect,
- colorBl: quadColor,
- colorBr: quadColor,
- colorTl: quadColor,
- colorTr: quadColor,
- width: canvasPages[0].texture?.dimensions?.width || 0,
- height: canvasPages[0].texture?.dimensions?.height || 0,
- texture: canvasPages[0].texture!,
- textureOptions: {},
- shader: null,
- shaderProps: null,
- zIndex,
- tx: transform.tx,
- ty: transform.ty - scrollY + renderWindow.y1,
- ta: transform.ta,
- tb: transform.tb,
- tc: transform.tc,
- td: transform.td,
- });
- }
- if (canvasPages[1].valid) {
- this.stage.renderer.addQuad({
- alpha: combinedAlpha,
- clippingRect,
- colorBl: quadColor,
- colorBr: quadColor,
- colorTl: quadColor,
- colorTr: quadColor,
- width: canvasPages[1].texture?.dimensions?.width || 0,
- height: canvasPages[1].texture?.dimensions?.height || 0,
- texture: canvasPages[1].texture!,
- textureOptions: {},
- shader: null,
- shaderProps: null,
- zIndex,
- tx: transform.tx,
- ty: transform.ty - scrollY + renderWindow.y1 + pageSize,
- ta: transform.ta,
- tb: transform.tb,
- tc: transform.tc,
- td: transform.td,
- });
- }
- if (canvasPages[2].valid) {
- this.stage.renderer.addQuad({
- alpha: combinedAlpha,
- clippingRect,
- colorBl: quadColor,
- colorBr: quadColor,
- colorTl: quadColor,
- colorTr: quadColor,
- width: canvasPages[2].texture?.dimensions?.width || 0,
- height: canvasPages[2].texture?.dimensions?.height || 0,
- texture: canvasPages[2].texture!,
- textureOptions: {},
- shader: null,
- shaderProps: null,
- zIndex,
- tx: transform.tx,
- ty: transform.ty - scrollY + renderWindow.y1 + pageSize + pageSize,
- ta: transform.ta,
- tb: transform.tb,
- tc: transform.tc,
- td: transform.td,
- });
+ // If font is not loaded, set up a handler to update the font info when the font loads
+ if (!state.fontInfo.loaded) {
+ globalFontSet
+ .load(cssString)
+ .then(this.onFontLoaded.bind(this, state, cssString))
+ .catch(this.onFontLoadError.bind(this, state, cssString));
+ return;
}
-
- // renderer.disableScissor();
-
- // if (debug.showElementRect) {
- // this.renderer.drawBorder(
- // Colors.Blue,
- // elementRect.x,
- // elementRect.y,
- // elementRect.w,
- // elementRect.h,
- // );
- // }
-
- // if (debug.showVisibleRect) {
- // this.renderer.drawBorder(
- // Colors.Green,
- // visibleRect.x,
- // visibleRect.y,
- // visibleRect.w,
- // visibleRect.h,
- // );
- // }
-
- // if (debug.showRenderWindow && renderWindow) {
- // this.renderer.drawBorder(
- // Colors.Red,
- // x + renderWindow.x1,
- // y + renderWindow.y1 - scrollY,
- // x + renderWindow.x2 - (x + renderWindow.x1),
- // y + renderWindow.y2 - scrollY - (y + renderWindow.y1 - scrollY),
- // );
- // }
+ };
+
+ calculateRenderInfo(state: CanvasTextRendererState): RenderInfo {
+ state.lightning2TextRenderer.settings = {
+ text: state.props.text,
+ textAlign: state.props.textAlign,
+ fontFamily: state.props.fontFamily,
+ trFontFace: state.fontInfo?.fontFace,
+ fontSize: state.props.fontSize,
+ fontStyle: [
+ state.props.fontStretch,
+ state.props.fontStyle,
+ state.props.fontWeight,
+ ].join(' '),
+ textColor: getNormalizedRgbaComponents(state.props.color),
+ offsetY: state.props.offsetY,
+ wordWrap: state.props.contain !== 'none',
+ wordWrapWidth:
+ state.props.contain === 'none' ? undefined : state.props.width,
+ letterSpacing: state.props.letterSpacing,
+ lineHeight: state.props.lineHeight ?? null,
+ maxLines: state.props.maxLines,
+ maxHeight:
+ state.props.contain === 'both'
+ ? state.props.height - state.props.offsetY
+ : null,
+ textBaseline: state.props.textBaseline,
+ verticalAlign: state.props.verticalAlign,
+ overflowSuffix: state.props.overflowSuffix,
+ w: state.props.contain !== 'none' ? state.props.width : undefined,
+ };
+ state.renderInfo = state.lightning2TextRenderer.calculateRenderInfo();
+ return state.renderInfo;
}
- override setIsRenderable(
- state: CanvasTextRendererState,
- renderable: boolean,
- ): void {
- super.setIsRenderable(state, renderable);
- // Set state object owner from any canvas page textures
- state.canvasPages?.forEach((pageInfo) => {
- pageInfo.texture?.setRenderableOwner(state, renderable);
- });
+ override renderQuads(): void {
+ // Do nothing. The renderer will render the child node(s) that were created
+ // in the state update.
+ return;
}
override destroyState(state: CanvasTextRendererState): void {
+ if (state.status === 'destroyed') {
+ return;
+ }
super.destroyState(state);
- // Remove state object owner from any canvas page textures
- state.canvasPages?.forEach((pageInfo) => {
- pageInfo.texture?.setRenderableOwner(state, false);
- });
- }
- //#endregion Overrides
- /**
- * Invalidate the visible window stored in the state. This will cause a new
- * visible window to be calculated on the next update.
- *
- * @param state
- */
- protected invalidateVisibleWindowCache(state: CanvasTextRendererState): void {
- state.visibleWindow.valid = false;
- this.setStatus(state, 'loading');
- this.scheduleUpdateState(state);
+ if (state.textureNode) {
+ state.textureNode.destroy();
+ delete state.textureNode;
+ }
+ delete state.renderInfo;
}
+ //#endregion Overrides
/**
* Invalidate the layout cache stored in the state. This will cause the text
- * to be re-layed out on the next update.
+ * to be re-rendered on the next update.
*
* @remarks
* This also invalidates the visible window cache.
@@ -774,7 +467,6 @@ export class CanvasTextRenderer extends TextRenderer {
*/
private invalidateLayoutCache(state: CanvasTextRendererState): void {
state.renderInfo = undefined;
- state.visibleWindow.valid = false;
this.setStatus(state, 'loading');
this.scheduleUpdateState(state);
}
diff --git a/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts b/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts
index 0e0c247c..27c01d82 100644
--- a/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts
+++ b/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts
@@ -166,7 +166,6 @@ export class LightningTextTextureRenderer {
| OffscreenCanvasRenderingContext2D
| CanvasRenderingContext2D;
private _settings: Settings;
- private renderInfo: RenderInfo | undefined;
constructor(
canvas: OffscreenCanvas | HTMLCanvasElement,
@@ -619,8 +618,6 @@ export class LightningTextTextureRenderer {
if (renderInfo.cutSx || renderInfo.cutSy) {
this._context.translate(renderInfo.cutSx, renderInfo.cutSy);
}
-
- this.renderInfo = renderInfo;
}
wrapWord(word: string, wordWrapWidth: number, suffix: string) {
diff --git a/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts b/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts
index d08d447a..382279b6 100644
--- a/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts
+++ b/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts
@@ -403,7 +403,7 @@ export class SdfTextRenderer extends TextRenderer {
this.setStatus(state, 'failed', new Error(msg));
return;
}
- trFontFace.texture.setRenderableOwner(state, state.isRenderable);
+ trFontFace.texture.setRenderableOwner(state, true);
}
// If the font hasn't been loaded yet, stop here.
@@ -712,7 +712,7 @@ export class SdfTextRenderer extends TextRenderer {
const texture = state.trFontFace?.texture;
assertTruthy(texture);
- const ctxTexture = this.stage.txManager.getCtxTexture(texture);
+ const ctxTexture = texture.ctxTexture;
renderOp.addTexture(ctxTexture as WebGlCoreCtxTexture);
renderOp.length = state.bufferNumFloats;
diff --git a/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts b/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts
index 429810a9..a8e1cc06 100644
--- a/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts
+++ b/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts
@@ -360,7 +360,8 @@ export function layoutText(
const xOffset = (vertexTextW - lineWidth) / 2;
for (let j = line.bufferStart; j < line.bufferEnd; j += 4) {
- vertexBuffer[j] += xOffset;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ vertexBuffer[j]! += xOffset;
}
}
} else if (textAlign === 'right') {
@@ -376,7 +377,8 @@ export function layoutText(
const xOffset = vertexTextW - lineWidth;
for (let j = line.bufferStart; j < line.bufferEnd; j += 4) {
- vertexBuffer[j] += xOffset;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ vertexBuffer[j]! += xOffset;
}
}
}
diff --git a/src/core/text-rendering/renderers/TextRenderer.ts b/src/core/text-rendering/renderers/TextRenderer.ts
index 28cb4fe7..cc655a8f 100644
--- a/src/core/text-rendering/renderers/TextRenderer.ts
+++ b/src/core/text-rendering/renderers/TextRenderer.ts
@@ -19,6 +19,7 @@
import type { Dimensions } from '../../../common/CommonTypes.js';
import type { EventEmitter } from '../../../common/EventEmitter.js';
+import type { CoreTextNode } from '../../CoreTextNode.js';
import type { Stage } from '../../Stage.js';
import type { Matrix3d } from '../../lib/Matrix3d.js';
import type { Rect, RectWithValid } from '../../lib/utils.js';
@@ -501,7 +502,7 @@ export abstract class TextRenderer<
*/
abstract addFontFace(fontFace: TrFontFace): void;
- abstract createState(props: TrProps): StateT;
+ abstract createState(props: TrProps, node: CoreTextNode): StateT;
/**
* Destroy/Clean up the state object
@@ -544,7 +545,7 @@ export abstract class TextRenderer<
abstract updateState(state: StateT): void;
- abstract renderQuads(
+ renderQuads?(
state: StateT,
transform: Matrix3d,
clippingRect: RectWithValid,
diff --git a/src/core/textures/ColorTexture.ts b/src/core/textures/ColorTexture.ts
index b9754c5b..ec561c9b 100644
--- a/src/core/textures/ColorTexture.ts
+++ b/src/core/textures/ColorTexture.ts
@@ -39,7 +39,7 @@ export interface ColorTextureProps {
* The pixel color is set with the {@link ColorTextureProps.color} prop.
*
* This is the default texture used for a Node if it's
- * {@link INodeWritableProps.texture} prop is set to `null` (the default)
+ * {@link INodeProps.texture} prop is set to `null` (the default)
*
* Generally the 1x1 color pixel is stretched to whatever the set dimensions of
* a Node are.
diff --git a/src/core/textures/ImageTexture.ts b/src/core/textures/ImageTexture.ts
index 0ecc9b5c..b521a3f9 100644
--- a/src/core/textures/ImageTexture.ts
+++ b/src/core/textures/ImageTexture.ts
@@ -38,7 +38,7 @@ export interface ImageTextureProps {
*
* @default ''
*/
- src?: string | ImageData | (() => ImageData);
+ src?: string | ImageData | (() => ImageData | null);
/**
* Whether to premultiply the alpha channel into the color channels of the
* image.
diff --git a/src/core/textures/NoiseTexture.ts b/src/core/textures/NoiseTexture.ts
index a634c71d..1b89c982 100644
--- a/src/core/textures/NoiseTexture.ts
+++ b/src/core/textures/NoiseTexture.ts
@@ -77,7 +77,10 @@ export class NoiseTexture extends Texture {
};
}
- static override makeCacheKey(props: NoiseTextureProps): string {
+ static override makeCacheKey(props: NoiseTextureProps): string | false {
+ if (props.cacheId === undefined) {
+ return false;
+ }
const resolvedProps = NoiseTexture.resolveDefaults(props);
return `NoiseTexture,${resolvedProps.width},${resolvedProps.height},${resolvedProps.cacheId}`;
}
diff --git a/src/core/textures/SubTexture.ts b/src/core/textures/SubTexture.ts
index 4fc322d0..e18a1ae6 100644
--- a/src/core/textures/SubTexture.ts
+++ b/src/core/textures/SubTexture.ts
@@ -17,7 +17,6 @@
* limitations under the License.
*/
-import type { TextureRef } from '../../main-api/RendererMain.js';
import type { CoreTextureManager } from '../CoreTextureManager.js';
import {
Texture,
@@ -33,7 +32,7 @@ export interface SubTextureProps {
/**
* The texture that this sub-texture is a sub-region of.
*/
- texture: TextureRef;
+ texture: Texture;
/**
* The x pixel position of the top-left of the sub-texture within the parent
@@ -80,12 +79,8 @@ export class SubTexture extends Texture {
constructor(txManager: CoreTextureManager, props: SubTextureProps) {
super(txManager);
- this.parentTexture = this.txManager.loadTexture(
- props.texture.txType,
- props.texture.props,
- props.texture.options,
- );
this.props = SubTexture.resolveDefaults(props || {});
+ this.parentTexture = this.props.texture;
// If parent texture is already loaded / failed, trigger loaded event manually
// so that users get a consistent event experience.
@@ -116,6 +111,11 @@ export class SubTexture extends Texture {
this.setState('failed', error);
};
+ override onChangeIsRenderable(isRenderable: boolean): void {
+ // Propagate the renderable owner change to the parent texture
+ this.parentTexture.setRenderableOwner(this, isRenderable);
+ }
+
override async getTextureData(): Promise