mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-18 10:44:33 +08:00
Gradio-lite (Gradio Wasm) (#4402)
This commit is contained in:
parent
3abad71ce4
commit
4fbdefe94e
@ -2,6 +2,7 @@
|
|||||||
**/pnpm-workspace.yaml
|
**/pnpm-workspace.yaml
|
||||||
**/js/app/dist/**
|
**/js/app/dist/**
|
||||||
**/client/js/dist/**
|
**/client/js/dist/**
|
||||||
|
**/js/lite/dist/**
|
||||||
**/pnpm-lock.yaml
|
**/pnpm-lock.yaml
|
||||||
**/js/plot/src/Plot.svelte
|
**/js/plot/src/Plot.svelte
|
||||||
**/.svelte-kit/**
|
**/.svelte-kit/**
|
||||||
|
2
.github/workflows/ui.yml
vendored
2
.github/workflows/ui.yml
vendored
@ -27,6 +27,8 @@ jobs:
|
|||||||
always-install-pnpm: true
|
always-install-pnpm: true
|
||||||
- name: build client
|
- name: build client
|
||||||
run: pnpm --filter @gradio/client build
|
run: pnpm --filter @gradio/client build
|
||||||
|
- name: build the wasm module
|
||||||
|
run: pnpm --filter @gradio/wasm build
|
||||||
- name: lint
|
- name: lint
|
||||||
run: pnpm lint
|
run: pnpm lint
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,8 @@
|
|||||||
export { client, post_data, upload_files, duplicate } from "./client.js";
|
export {
|
||||||
|
client,
|
||||||
|
post_data,
|
||||||
|
upload_files,
|
||||||
|
duplicate,
|
||||||
|
api_factory
|
||||||
|
} from "./client.js";
|
||||||
export type { SpaceStatus } from "./types.js";
|
export type { SpaceStatus } from "./types.js";
|
||||||
|
@ -32,6 +32,7 @@ from gradio import (
|
|||||||
strings,
|
strings,
|
||||||
themes,
|
themes,
|
||||||
utils,
|
utils,
|
||||||
|
wasm_utils,
|
||||||
)
|
)
|
||||||
from gradio.context import Context
|
from gradio.context import Context
|
||||||
from gradio.deprecation import check_deprecated_parameters
|
from gradio.deprecation import check_deprecated_parameters
|
||||||
@ -739,7 +740,7 @@ class Blocks(BlockContext):
|
|||||||
self.root_path = ""
|
self.root_path = ""
|
||||||
self.root_urls = set()
|
self.root_urls = set()
|
||||||
|
|
||||||
if self.analytics_enabled:
|
if not wasm_utils.IS_WASM and self.analytics_enabled:
|
||||||
is_custom_theme = not any(
|
is_custom_theme = not any(
|
||||||
self.theme.to_dict() == built_in_theme.to_dict()
|
self.theme.to_dict() == built_in_theme.to_dict()
|
||||||
for built_in_theme in BUILT_IN_THEMES.values()
|
for built_in_theme in BUILT_IN_THEMES.values()
|
||||||
@ -1772,15 +1773,37 @@ Received outputs:
|
|||||||
"Rerunning server... use `close()` to stop if you need to change `launch()` parameters.\n----"
|
"Rerunning server... use `close()` to stop if you need to change `launch()` parameters.\n----"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
server_name, server_port, local_url, app, server = networking.start_server(
|
if wasm_utils.IS_WASM:
|
||||||
self,
|
server_name = "xxx"
|
||||||
server_name,
|
server_port = 99999
|
||||||
server_port,
|
local_url = ""
|
||||||
ssl_keyfile,
|
server = None
|
||||||
ssl_certfile,
|
|
||||||
ssl_keyfile_password,
|
# In the Wasm environment, we only need the app object
|
||||||
app_kwargs=app_kwargs,
|
# which the frontend app will directly communicate with through the Worker API,
|
||||||
)
|
# and we don't need to start a server.
|
||||||
|
# So we just create the app object and register it here,
|
||||||
|
# and avoid using `networking.start_server` that would start a server that don't work in the Wasm env.
|
||||||
|
from gradio.routes import App
|
||||||
|
|
||||||
|
app = App.create_app(self, app_kwargs=app_kwargs)
|
||||||
|
wasm_utils.register_app(app)
|
||||||
|
else:
|
||||||
|
(
|
||||||
|
server_name,
|
||||||
|
server_port,
|
||||||
|
local_url,
|
||||||
|
app,
|
||||||
|
server,
|
||||||
|
) = networking.start_server(
|
||||||
|
self,
|
||||||
|
server_name,
|
||||||
|
server_port,
|
||||||
|
ssl_keyfile,
|
||||||
|
ssl_certfile,
|
||||||
|
ssl_keyfile_password,
|
||||||
|
app_kwargs=app_kwargs,
|
||||||
|
)
|
||||||
self.server_name = server_name
|
self.server_name = server_name
|
||||||
self.local_url = local_url
|
self.local_url = local_url
|
||||||
self.server_port = server_port
|
self.server_port = server_port
|
||||||
@ -1802,7 +1825,11 @@ Received outputs:
|
|||||||
|
|
||||||
# Cannot run async functions in background other than app's scope.
|
# Cannot run async functions in background other than app's scope.
|
||||||
# Workaround by triggering the app endpoint
|
# Workaround by triggering the app endpoint
|
||||||
requests.get(f"{self.local_url}startup-events", verify=ssl_verify)
|
if not wasm_utils.IS_WASM:
|
||||||
|
requests.get(f"{self.local_url}startup-events", verify=ssl_verify)
|
||||||
|
|
||||||
|
if wasm_utils.IS_WASM:
|
||||||
|
return TupleNoPrint((self.server_app, self.local_url, self.share_url))
|
||||||
|
|
||||||
utils.launch_counter()
|
utils.launch_counter()
|
||||||
|
|
||||||
@ -2037,7 +2064,8 @@ Received outputs:
|
|||||||
try:
|
try:
|
||||||
if self.enable_queue:
|
if self.enable_queue:
|
||||||
self._queue.close()
|
self._queue.close()
|
||||||
self.server.close()
|
if self.server:
|
||||||
|
self.server.close()
|
||||||
self.is_running = False
|
self.is_running = False
|
||||||
# So that the startup events (starting the queue)
|
# So that the startup events (starting the queue)
|
||||||
# happen the next time the app is launched
|
# happen the next time the app is launched
|
||||||
@ -2056,7 +2084,8 @@ Received outputs:
|
|||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
except (KeyboardInterrupt, OSError):
|
except (KeyboardInterrupt, OSError):
|
||||||
print("Keyboard interruption in main thread... closing server.")
|
print("Keyboard interruption in main thread... closing server.")
|
||||||
self.server.close()
|
if self.server:
|
||||||
|
self.server.close()
|
||||||
for tunnel in CURRENT_TUNNELS:
|
for tunnel in CURRENT_TUNNELS:
|
||||||
tunnel.kill()
|
tunnel.kill()
|
||||||
|
|
||||||
|
@ -7,16 +7,19 @@ import warnings
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Callable, Literal
|
from typing import Callable, Literal
|
||||||
|
|
||||||
from ffmpy import FFmpeg
|
|
||||||
from gradio_client import utils as client_utils
|
from gradio_client import utils as client_utils
|
||||||
from gradio_client.data_classes import FileData
|
from gradio_client.data_classes import FileData
|
||||||
from gradio_client.documentation import document, set_documentation_group
|
from gradio_client.documentation import document, set_documentation_group
|
||||||
from gradio_client.serializing import VideoSerializable
|
from gradio_client.serializing import VideoSerializable
|
||||||
|
|
||||||
from gradio import processing_utils, utils
|
from gradio import processing_utils, utils, wasm_utils
|
||||||
from gradio.components.base import IOComponent, _Keywords
|
from gradio.components.base import IOComponent, _Keywords
|
||||||
from gradio.events import Changeable, Clearable, Playable, Recordable, Uploadable
|
from gradio.events import Changeable, Clearable, Playable, Recordable, Uploadable
|
||||||
|
|
||||||
|
if not wasm_utils.IS_WASM:
|
||||||
|
# TODO: Support ffmpeg on Wasm
|
||||||
|
from ffmpy import FFmpeg
|
||||||
|
|
||||||
set_documentation_group("component")
|
set_documentation_group("component")
|
||||||
|
|
||||||
|
|
||||||
@ -204,6 +207,10 @@ class Video(
|
|||||||
)
|
)
|
||||||
if Path(output_file_name).exists():
|
if Path(output_file_name).exists():
|
||||||
return output_file_name
|
return output_file_name
|
||||||
|
if wasm_utils.IS_WASM:
|
||||||
|
raise wasm_utils.WasmUnsupportedError(
|
||||||
|
"Video formatting is not supported in the Wasm mode."
|
||||||
|
)
|
||||||
ff = FFmpeg(
|
ff = FFmpeg(
|
||||||
inputs={str(file_name): None},
|
inputs={str(file_name): None},
|
||||||
outputs={output_file_name: output_options},
|
outputs={output_file_name: output_options},
|
||||||
@ -212,6 +219,10 @@ class Video(
|
|||||||
return output_file_name
|
return output_file_name
|
||||||
elif not self.include_audio:
|
elif not self.include_audio:
|
||||||
output_file_name = str(file_name.with_name(f"muted_{file_name.name}"))
|
output_file_name = str(file_name.with_name(f"muted_{file_name.name}"))
|
||||||
|
if wasm_utils.IS_WASM:
|
||||||
|
raise wasm_utils.WasmUnsupportedError(
|
||||||
|
"include_audio=False is not supported in the Wasm mode."
|
||||||
|
)
|
||||||
ff = FFmpeg(
|
ff = FFmpeg(
|
||||||
inputs={str(file_name): None},
|
inputs={str(file_name): None},
|
||||||
outputs={output_file_name: ["-an"]},
|
outputs={output_file_name: ["-an"]},
|
||||||
@ -301,6 +312,10 @@ class Video(
|
|||||||
# selected format
|
# selected format
|
||||||
returned_format = video.split(".")[-1].lower()
|
returned_format = video.split(".")[-1].lower()
|
||||||
if self.format is not None and returned_format != self.format:
|
if self.format is not None and returned_format != self.format:
|
||||||
|
if wasm_utils.IS_WASM:
|
||||||
|
raise wasm_utils.WasmUnsupportedError(
|
||||||
|
"Returning a video in a different format is not supported in the Wasm mode."
|
||||||
|
)
|
||||||
output_file_name = video[0 : video.rindex(".") + 1] + self.format
|
output_file_name = video[0 : video.rindex(".") + 1] + self.format
|
||||||
ff = FFmpeg(
|
ff = FFmpeg(
|
||||||
inputs={video: None},
|
inputs={video: None},
|
||||||
|
@ -11,10 +11,15 @@ from io import BytesIO
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ffmpy import FFmpeg, FFprobe, FFRuntimeError
|
|
||||||
from gradio_client import utils as client_utils
|
from gradio_client import utils as client_utils
|
||||||
from PIL import Image, ImageOps, PngImagePlugin
|
from PIL import Image, ImageOps, PngImagePlugin
|
||||||
|
|
||||||
|
from gradio import wasm_utils
|
||||||
|
|
||||||
|
if not wasm_utils.IS_WASM:
|
||||||
|
# TODO: Support ffmpeg on Wasm
|
||||||
|
from ffmpy import FFmpeg, FFprobe, FFRuntimeError
|
||||||
|
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
warnings.simplefilter("ignore") # Ignore pydub warning if ffmpeg is not installed
|
warnings.simplefilter("ignore") # Ignore pydub warning if ffmpeg is not installed
|
||||||
from pydub import AudioSegment
|
from pydub import AudioSegment
|
||||||
@ -478,6 +483,10 @@ def _convert(image, dtype, force_copy=False, uniform=False):
|
|||||||
|
|
||||||
|
|
||||||
def ffmpeg_installed() -> bool:
|
def ffmpeg_installed() -> bool:
|
||||||
|
if wasm_utils.IS_WASM:
|
||||||
|
# TODO: Support ffmpeg in WASM
|
||||||
|
return False
|
||||||
|
|
||||||
return shutil.which("ffmpeg") is not None
|
return shutil.which("ffmpeg") is not None
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ from starlette.websockets import WebSocketState
|
|||||||
|
|
||||||
import gradio
|
import gradio
|
||||||
import gradio.ranged_response as ranged_response
|
import gradio.ranged_response as ranged_response
|
||||||
from gradio import utils
|
from gradio import utils, wasm_utils
|
||||||
from gradio.context import Context
|
from gradio.context import Context
|
||||||
from gradio.data_classes import PredictBody, ResetBody
|
from gradio.data_classes import PredictBody, ResetBody
|
||||||
from gradio.exceptions import Error
|
from gradio.exceptions import Error
|
||||||
@ -167,16 +167,18 @@ class App(FastAPI):
|
|||||||
blocks: gradio.Blocks, app_kwargs: Dict[str, Any] | None = None
|
blocks: gradio.Blocks, app_kwargs: Dict[str, Any] | None = None
|
||||||
) -> App:
|
) -> App:
|
||||||
app_kwargs = app_kwargs or {}
|
app_kwargs = app_kwargs or {}
|
||||||
app_kwargs.setdefault("default_response_class", ORJSONResponse)
|
if not wasm_utils.IS_WASM:
|
||||||
|
app_kwargs.setdefault("default_response_class", ORJSONResponse)
|
||||||
app = App(**app_kwargs)
|
app = App(**app_kwargs)
|
||||||
app.configure_app(blocks)
|
app.configure_app(blocks)
|
||||||
|
|
||||||
app.add_middleware(
|
if not wasm_utils.IS_WASM:
|
||||||
CORSMiddleware,
|
app.add_middleware(
|
||||||
allow_origins=["*"],
|
CORSMiddleware,
|
||||||
allow_methods=["*"],
|
allow_origins=["*"],
|
||||||
allow_headers=["*"],
|
allow_methods=["*"],
|
||||||
)
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
@app.get("/user")
|
@app.get("/user")
|
||||||
@app.get("/user/")
|
@app.get("/user/")
|
||||||
|
@ -4,6 +4,8 @@ from typing import Dict
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from gradio import wasm_utils
|
||||||
|
|
||||||
MESSAGING_API_ENDPOINT = "https://api.gradio.app/gradio-messaging/en"
|
MESSAGING_API_ENDPOINT = "https://api.gradio.app/gradio-messaging/en"
|
||||||
|
|
||||||
en = {
|
en = {
|
||||||
@ -41,5 +43,5 @@ def get_updated_messaging(en: Dict):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
if os.getenv("GRADIO_ANALYTICS_ENABLED", "True") == "True":
|
if os.getenv("GRADIO_ANALYTICS_ENABLED", "True") == "True" and not wasm_utils.IS_WASM:
|
||||||
threading.Thread(target=get_updated_messaging, args=(en,)).start()
|
threading.Thread(target=get_updated_messaging, args=(en,)).start()
|
||||||
|
24
gradio/wasm_utils.py
Normal file
24
gradio/wasm_utils.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
# See https://pyodide.org/en/stable/usage/faq.html#how-to-detect-that-code-is-run-with-pyodide
|
||||||
|
IS_WASM = sys.platform == "emscripten"
|
||||||
|
|
||||||
|
|
||||||
|
class WasmUnsupportedError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
app = None
|
||||||
|
|
||||||
|
|
||||||
|
# `register_app` and `get_registered_app` are used
|
||||||
|
# for the Wasm worker to get a reference to
|
||||||
|
# the Gradio's FastAPI app instance (`app`).
|
||||||
|
def register_app(_app):
|
||||||
|
global app
|
||||||
|
app = _app
|
||||||
|
|
||||||
|
|
||||||
|
def get_registered_app():
|
||||||
|
global app
|
||||||
|
return app
|
43
js/app/lite.html
Normal file
43
js/app/lite.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- An entrypoint for the Wasm version development -->
|
||||||
|
<html
|
||||||
|
lang="en"
|
||||||
|
style="
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<script type="module" src="./src/lite/index.ts"></script>
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link
|
||||||
|
rel="preconnect"
|
||||||
|
href="https://fonts.gstatic.com"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
/>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body
|
||||||
|
style="
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div id="gradio-app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -5,9 +5,14 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --port 9876",
|
"dev": "vite --port 9876",
|
||||||
|
"dev:lite": "vite --port 9876 --mode development:lite",
|
||||||
"build:cdn": "vite build --mode production:cdn --emptyOutDir",
|
"build:cdn": "vite build --mode production:cdn --emptyOutDir",
|
||||||
"build:website": "vite build --mode production:website --emptyOutDir",
|
"build:website": "vite build --mode production:website --emptyOutDir",
|
||||||
"build:local": "vite build --mode production:local --emptyOutDir",
|
"build:local": "vite build --mode production:local --emptyOutDir",
|
||||||
|
"pybuild:gradio": "cd ../../ && rm -rf gradio/templates/frontend && python3 -m build",
|
||||||
|
"pybuild:gradio-client": "cd ../../client/python && python3 -m build",
|
||||||
|
"pybuild": "run-p pybuild:*",
|
||||||
|
"build:lite": "pnpm pybuild && vite build --mode production:lite --emptyOutDir",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test:snapshot": "pnpm exec playwright test snapshots/ --config=../../.config/playwright.config.js",
|
"test:snapshot": "pnpm exec playwright test snapshots/ --config=../../.config/playwright.config.js",
|
||||||
"test:browser": "pnpm exec playwright test test/ --config=../../.config/playwright.config.js",
|
"test:browser": "pnpm exec playwright test test/ --config=../../.config/playwright.config.js",
|
||||||
@ -42,6 +47,7 @@
|
|||||||
"@gradio/upload-button": "workspace:^0.0.1",
|
"@gradio/upload-button": "workspace:^0.0.1",
|
||||||
"@gradio/utils": "workspace:^0.0.1",
|
"@gradio/utils": "workspace:^0.0.1",
|
||||||
"@gradio/video": "workspace:^0.0.1",
|
"@gradio/video": "workspace:^0.0.1",
|
||||||
|
"@gradio/wasm": "workspace:^0.0.1",
|
||||||
"@playwright/test": "^1.35.1",
|
"@playwright/test": "^1.35.1",
|
||||||
"d3-dsv": "^3.0.1",
|
"d3-dsv": "^3.0.1",
|
||||||
"mime-types": "^2.1.34",
|
"mime-types": "^2.1.34",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script context="module" lang="ts">
|
<script context="module" lang="ts">
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { mount_css } from "./css";
|
import { mount_css as default_mount_css } from "./css";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ComponentMeta,
|
ComponentMeta,
|
||||||
@ -58,8 +58,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import { onMount, setContext } from "svelte";
|
||||||
import { client, SpaceStatus } from "@gradio/client";
|
import type { api_factory, SpaceStatus } from "@gradio/client";
|
||||||
|
|
||||||
import Embed from "./Embed.svelte";
|
import Embed from "./Embed.svelte";
|
||||||
import type { ThemeMode } from "./components/types";
|
import type { ThemeMode } from "./components/types";
|
||||||
@ -76,6 +76,11 @@
|
|||||||
export let info: boolean;
|
export let info: boolean;
|
||||||
export let eager: boolean;
|
export let eager: boolean;
|
||||||
|
|
||||||
|
// These utilities are exported to be injectable for the Wasm version.
|
||||||
|
export let mount_css: typeof default_mount_css = default_mount_css;
|
||||||
|
export let client: ReturnType<typeof api_factory>["client"];
|
||||||
|
export let upload_files: ReturnType<typeof api_factory>["upload_files"];
|
||||||
|
|
||||||
export let space: string | null;
|
export let space: string | null;
|
||||||
export let host: string | null;
|
export let host: string | null;
|
||||||
export let src: string | null;
|
export let src: string | null;
|
||||||
@ -216,6 +221,8 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setContext("upload_files", upload_files);
|
||||||
|
|
||||||
$: loader_status =
|
$: loader_status =
|
||||||
!ready && status.load_status !== "error"
|
!ready && status.load_status !== "error"
|
||||||
? "pending"
|
? "pending"
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
import { File as FileComponent, FileUpload } from "@gradio/file";
|
import { File as FileComponent, FileUpload } from "@gradio/file";
|
||||||
import { blobToBase64, FileData } from "@gradio/upload";
|
import { blobToBase64, FileData } from "@gradio/upload";
|
||||||
import { normalise_file } from "@gradio/upload";
|
import { normalise_file } from "@gradio/upload";
|
||||||
import { Block } from "@gradio/atoms";
|
import { Block } from "@gradio/atoms";
|
||||||
import UploadText from "../UploadText.svelte";
|
import UploadText from "../UploadText.svelte";
|
||||||
import { upload_files } from "@gradio/client";
|
import { upload_files as default_upload_files } from "@gradio/client";
|
||||||
|
|
||||||
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
|
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
|
||||||
import type { LoadingStatus } from "../StatusTracker/types";
|
import type { LoadingStatus } from "../StatusTracker/types";
|
||||||
@ -31,6 +31,10 @@
|
|||||||
export let scale: number | null = null;
|
export let scale: number | null = null;
|
||||||
export let min_width: number | undefined = undefined;
|
export let min_width: number | undefined = undefined;
|
||||||
|
|
||||||
|
const upload_files =
|
||||||
|
getContext<typeof default_upload_files>("upload_files") ??
|
||||||
|
default_upload_files;
|
||||||
|
|
||||||
$: _value = normalise_file(value, root, root_url);
|
$: _value = normalise_file(value, root, root_url);
|
||||||
|
|
||||||
let dragging = false;
|
let dragging = false;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher, tick } from "svelte";
|
import { createEventDispatcher, tick, getContext } from "svelte";
|
||||||
import type { FileData } from "@gradio/upload";
|
import type { FileData } from "@gradio/upload";
|
||||||
import { UploadButton } from "@gradio/upload-button";
|
import { UploadButton } from "@gradio/upload-button";
|
||||||
import { upload_files } from "@gradio/client";
|
import { upload_files as default_upload_files } from "@gradio/client";
|
||||||
import { blobToBase64 } from "@gradio/upload";
|
import { blobToBase64 } from "@gradio/upload";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
|
|
||||||
@ -20,6 +20,10 @@
|
|||||||
export let mode: "static" | "dynamic" = "dynamic";
|
export let mode: "static" | "dynamic" = "dynamic";
|
||||||
export let variant: "primary" | "secondary" | "stop" = "secondary";
|
export let variant: "primary" | "secondary" | "stop" = "secondary";
|
||||||
|
|
||||||
|
const upload_files =
|
||||||
|
getContext<typeof default_upload_files>("upload_files") ??
|
||||||
|
default_upload_files;
|
||||||
|
|
||||||
async function handle_upload({ detail }: CustomEvent<FileData>) {
|
async function handle_upload({ detail }: CustomEvent<FileData>) {
|
||||||
value = detail;
|
value = detail;
|
||||||
await tick();
|
await tick();
|
||||||
|
36
js/app/src/lite/css.ts
Normal file
36
js/app/src/lite/css.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import type { WorkerProxy } from "@gradio/wasm";
|
||||||
|
import { is_self_origin } from "./url";
|
||||||
|
import { mount_css as default_mount_css } from "../css";
|
||||||
|
|
||||||
|
export async function wasm_proxied_mount_css(
|
||||||
|
worker_proxy: WorkerProxy,
|
||||||
|
url_string: string,
|
||||||
|
target: HTMLElement
|
||||||
|
) {
|
||||||
|
const request = new Request(url_string); // Resolve a relative URL.
|
||||||
|
const url = new URL(request.url);
|
||||||
|
|
||||||
|
if (!is_self_origin(url)) {
|
||||||
|
// Fallback to the default implementation for external resources.
|
||||||
|
return default_mount_css(url_string, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await worker_proxy.httpRequest({
|
||||||
|
method: "GET",
|
||||||
|
path: url.pathname,
|
||||||
|
query_string: "",
|
||||||
|
headers: {}
|
||||||
|
});
|
||||||
|
const css = new TextDecoder().decode(response.body);
|
||||||
|
|
||||||
|
const existing_link = document.querySelector(
|
||||||
|
`style[data-wasm-path='${url_string}']`
|
||||||
|
);
|
||||||
|
if (existing_link) return;
|
||||||
|
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.setAttribute("data-wasm-path", url_string);
|
||||||
|
style.textContent = css;
|
||||||
|
// @ts-ignore
|
||||||
|
target.appendChild(style);
|
||||||
|
}
|
54
js/app/src/lite/fetch.ts
Normal file
54
js/app/src/lite/fetch.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import type { WorkerProxy } from "@gradio/wasm";
|
||||||
|
import { is_self_origin } from "./url";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fetch() function that proxies HTTP requests to the worker,
|
||||||
|
* which also falls back to the original fetch() for external resource requests.
|
||||||
|
*/
|
||||||
|
export async function wasm_proxied_fetch(
|
||||||
|
workerProxy: WorkerProxy,
|
||||||
|
input: RequestInfo | URL,
|
||||||
|
init?: RequestInit
|
||||||
|
): Promise<Response> {
|
||||||
|
console.debug("wasm_proxied_fetch", input, init);
|
||||||
|
|
||||||
|
const request = new Request(input, init);
|
||||||
|
|
||||||
|
const url = new URL(request.url);
|
||||||
|
|
||||||
|
if (!is_self_origin(url)) {
|
||||||
|
console.debug("Fallback to original fetch");
|
||||||
|
return fetch(input, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
const method = request.method;
|
||||||
|
if (
|
||||||
|
method !== "GET" &&
|
||||||
|
method !== "POST" &&
|
||||||
|
method !== "PUT" &&
|
||||||
|
method !== "DELETE"
|
||||||
|
) {
|
||||||
|
throw new Error(`Unsupported method: ${method}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers: Parameters<WorkerProxy["httpRequest"]>[0]["headers"] = {};
|
||||||
|
request.headers.forEach((value, key) => {
|
||||||
|
headers[key] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const bodyArrayBuffer = await new Response(request.body).arrayBuffer();
|
||||||
|
const body: Parameters<WorkerProxy["httpRequest"]>[0]["body"] =
|
||||||
|
new Uint8Array(bodyArrayBuffer);
|
||||||
|
|
||||||
|
const response = await workerProxy.httpRequest({
|
||||||
|
path: url.pathname,
|
||||||
|
query_string: url.search,
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
body
|
||||||
|
});
|
||||||
|
return new Response(response.body, {
|
||||||
|
status: response.status,
|
||||||
|
headers: new Headers(response.headers)
|
||||||
|
});
|
||||||
|
}
|
162
js/app/src/lite/index.ts
Normal file
162
js/app/src/lite/index.ts
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import "@gradio/theme";
|
||||||
|
import { WorkerProxy } from "@gradio/wasm";
|
||||||
|
import { api_factory } from "@gradio/client";
|
||||||
|
import { wasm_proxied_fetch } from "./fetch";
|
||||||
|
import { wasm_proxied_mount_css } from "./css";
|
||||||
|
import type { mount_css } from "../css";
|
||||||
|
import Index from "../Index.svelte";
|
||||||
|
import type { ThemeMode } from "../components/types";
|
||||||
|
|
||||||
|
// These imports are aliased at built time with Vite. See the `resolve.alias` config in `vite.config.ts`.
|
||||||
|
import gradioWheel from "gradio.whl";
|
||||||
|
import gradioClientWheel from "gradio_client.whl";
|
||||||
|
|
||||||
|
declare let GRADIO_VERSION: string;
|
||||||
|
|
||||||
|
// NOTE: The following line has been copied from `main.ts`.
|
||||||
|
// In `main.ts`, which is the normal Gradio app entry point,
|
||||||
|
// the string literal "__ENTRY_CSS__" will be replaced with the actual CSS file path
|
||||||
|
// by the Vite plugin `handle_ce_css` in `build_plugins.ts`,
|
||||||
|
// and the CSS file will be dynamically loaded at runtime
|
||||||
|
// as the file path (the `ENTRY_CSS` variable) will be passed to `mount_css()`.
|
||||||
|
// This mechanism has been introduced in https://github.com/gradio-app/gradio/pull/1444
|
||||||
|
// to make Gradio work as a Web Component library
|
||||||
|
// with which users can use Gradio by loading only one JS file,
|
||||||
|
// without a link tag referring to the CSS file.
|
||||||
|
// However, we don't rely on this mechanism here to make things simpler by leaving the Vite plugins as is,
|
||||||
|
// because it will be refactored in the near future.
|
||||||
|
// As a result, the users of the Wasm app will have to load the CSS file manually.
|
||||||
|
// const ENTRY_CSS = "__ENTRY_CSS__";
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
target: HTMLElement;
|
||||||
|
pyCode: string;
|
||||||
|
info: boolean;
|
||||||
|
container: boolean;
|
||||||
|
isEmbed: boolean;
|
||||||
|
initialHeight?: string;
|
||||||
|
eager: boolean;
|
||||||
|
themeMode: ThemeMode | null;
|
||||||
|
autoScroll: boolean;
|
||||||
|
controlPageTitle: boolean;
|
||||||
|
appMode: boolean;
|
||||||
|
}
|
||||||
|
export async function create(options: Options) {
|
||||||
|
// TODO: Runtime type validation for options.
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
document.body.style.padding = "0";
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(options.target, { childList: true });
|
||||||
|
|
||||||
|
const worker_proxy = new WorkerProxy({
|
||||||
|
gradioWheelUrl: gradioWheel,
|
||||||
|
gradioClientWheelUrl: gradioClientWheel,
|
||||||
|
requirements: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Internally, the execution of `runPythonAsync()` is queued
|
||||||
|
// and its promise will be resolved after the Pyodide is loaded and the worker initialization is done
|
||||||
|
// (see the await in the `onmessage` callback in the webworker code)
|
||||||
|
// So we don't await this promise because we want to mount the `Index` immediately and start the app initialization asynchronously.
|
||||||
|
worker_proxy.runPythonAsync(options.pyCode);
|
||||||
|
|
||||||
|
const overridden_fetch: typeof fetch = (input, init?) => {
|
||||||
|
return wasm_proxied_fetch(worker_proxy, input, init);
|
||||||
|
};
|
||||||
|
const { client, upload_files } = api_factory(overridden_fetch);
|
||||||
|
const overridden_mount_css: typeof mount_css = async (url, target) => {
|
||||||
|
return wasm_proxied_mount_css(worker_proxy, url, target);
|
||||||
|
};
|
||||||
|
|
||||||
|
const app = new Index({
|
||||||
|
target: options.target,
|
||||||
|
props: {
|
||||||
|
// embed source
|
||||||
|
space: null,
|
||||||
|
src: null,
|
||||||
|
host: null,
|
||||||
|
// embed info
|
||||||
|
info: options.info,
|
||||||
|
container: options.container,
|
||||||
|
is_embed: options.isEmbed,
|
||||||
|
initial_height: options.initialHeight ?? "300px", // default: 300px
|
||||||
|
eager: options.eager,
|
||||||
|
// gradio meta info
|
||||||
|
version: GRADIO_VERSION,
|
||||||
|
theme_mode: options.themeMode,
|
||||||
|
// misc global behaviour
|
||||||
|
autoscroll: options.autoScroll,
|
||||||
|
control_page_title: options.controlPageTitle,
|
||||||
|
// for gradio docs
|
||||||
|
// TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds
|
||||||
|
app_mode: options.appMode,
|
||||||
|
// For Wasm mode
|
||||||
|
client,
|
||||||
|
upload_files,
|
||||||
|
mount_css: overridden_mount_css
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I'm not sure if this is a correct way to export functions from a bundle created with Vite.
|
||||||
|
* However, at least, the library mode (https://vitejs.dev/guide/build.html#library-mode)
|
||||||
|
* with an exported function (`export async function create()`) didn't work for our case.
|
||||||
|
* In library mode with the `build.lib.entry = (this file)` config,
|
||||||
|
* Vite creates a bundle exporting the functions from this file, which looks nice,
|
||||||
|
* however, it inevitably enables inlining of all the static file assets,
|
||||||
|
* while we need to disable inlining for the wheel files to pass their URLs to `micropip.install()`.
|
||||||
|
*
|
||||||
|
* > If you specify build.lib, build.assetsInlineLimit will be ignored and assets will always be inlined, regardless of file size or being a Git LFS placeholder.
|
||||||
|
* > https://vitejs.dev/config/build-options.html#build-assetsinlinelimit
|
||||||
|
*
|
||||||
|
* There is an open issue about this: https://github.com/vitejs/vite/issues/4454
|
||||||
|
*
|
||||||
|
* FYI, stlite (https://github.com/whitphx/stlite) uses Webpack,
|
||||||
|
* which supports bundling libraries that export entities to the global scope and disabling assets inlining
|
||||||
|
* (https://webpack.js.org/guides/author-libraries/).
|
||||||
|
*/
|
||||||
|
// @ts-ignore
|
||||||
|
globalThis.createGradioApp = create;
|
||||||
|
|
||||||
|
declare let BUILD_MODE: string;
|
||||||
|
if (BUILD_MODE === "dev") {
|
||||||
|
create({
|
||||||
|
target: document.getElementById("gradio-app")!,
|
||||||
|
pyCode: `
|
||||||
|
import gradio as gr
|
||||||
|
|
||||||
|
def greet(name):
|
||||||
|
return "Hello " + name + "!"
|
||||||
|
|
||||||
|
def upload_file(files):
|
||||||
|
file_paths = [file.name for file in files]
|
||||||
|
return file_paths
|
||||||
|
|
||||||
|
with gr.Blocks() as demo:
|
||||||
|
name = gr.Textbox(label="Name")
|
||||||
|
output = gr.Textbox(label="Output Box")
|
||||||
|
greet_btn = gr.Button("Greet")
|
||||||
|
greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
|
||||||
|
|
||||||
|
gr.File()
|
||||||
|
|
||||||
|
file_output = gr.File()
|
||||||
|
upload_button = gr.UploadButton("Click to Upload a File", file_types=["image", "video"], file_count="multiple")
|
||||||
|
upload_button.upload(upload_file, upload_button, file_output)
|
||||||
|
|
||||||
|
demo.launch()
|
||||||
|
`,
|
||||||
|
info: true,
|
||||||
|
container: true,
|
||||||
|
isEmbed: false,
|
||||||
|
initialHeight: "300px",
|
||||||
|
eager: false,
|
||||||
|
themeMode: null,
|
||||||
|
autoScroll: false,
|
||||||
|
controlPageTitle: false,
|
||||||
|
appMode: true
|
||||||
|
});
|
||||||
|
}
|
6
js/app/src/lite/url.ts
Normal file
6
js/app/src/lite/url.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export function is_self_origin(url: URL): boolean {
|
||||||
|
return (
|
||||||
|
url.origin === window.location.origin ||
|
||||||
|
url.origin === "http://localhost:7860" // Ref: https://github.com/gradio-app/gradio/blob/v3.32.0/js/app/src/Index.svelte#L194
|
||||||
|
);
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import "@gradio/theme";
|
import "@gradio/theme";
|
||||||
|
import { client, upload_files } from "@gradio/client";
|
||||||
import { mount_css } from "./css";
|
import { mount_css } from "./css";
|
||||||
import Index from "./Index.svelte";
|
import Index from "./Index.svelte";
|
||||||
import type { ThemeMode } from "./components/types";
|
import type { ThemeMode } from "./components/types";
|
||||||
@ -93,6 +94,9 @@ function create_custom_element() {
|
|||||||
// misc global behaviour
|
// misc global behaviour
|
||||||
autoscroll: this.autoscroll === "true" ? true : false,
|
autoscroll: this.autoscroll === "true" ? true : false,
|
||||||
control_page_title: this.control_page_title === "true" ? true : false,
|
control_page_title: this.control_page_title === "true" ? true : false,
|
||||||
|
// injectables
|
||||||
|
client,
|
||||||
|
upload_files,
|
||||||
// for gradio docs
|
// for gradio docs
|
||||||
// TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds
|
// TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds
|
||||||
app_mode: window.__gradio_mode__ === "app"
|
app_mode: window.__gradio_mode__ === "app"
|
||||||
@ -154,6 +158,9 @@ function create_custom_element() {
|
|||||||
autoscroll: this.autoscroll === "true" ? true : false,
|
autoscroll: this.autoscroll === "true" ? true : false,
|
||||||
control_page_title:
|
control_page_title:
|
||||||
this.control_page_title === "true" ? true : false,
|
this.control_page_title === "true" ? true : false,
|
||||||
|
// injectables
|
||||||
|
client,
|
||||||
|
upload_files,
|
||||||
// for gradio docs
|
// for gradio docs
|
||||||
// TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds
|
// TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds
|
||||||
app_mode: window.__gradio_mode__ === "app"
|
app_mode: window.__gradio_mode__ === "app"
|
||||||
|
6
js/app/src/vite-env-override.d.ts
vendored
Normal file
6
js/app/src/vite-env-override.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// See https://vitejs.dev/guide/features.html#client-types
|
||||||
|
|
||||||
|
declare module "*.whl" {
|
||||||
|
const content: string;
|
||||||
|
export default content;
|
||||||
|
}
|
@ -7,14 +7,21 @@ import global_data from "@csstools/postcss-global-data";
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import prefixer from "postcss-prefix-selector";
|
import prefixer from "postcss-prefix-selector";
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { join } from "path";
|
import { resolve } from "path";
|
||||||
|
|
||||||
const version_path = join(__dirname, "..", "..", "gradio", "version.txt");
|
const version_path = resolve(__dirname, "../../gradio/version.txt");
|
||||||
const theme_token_path = join(__dirname, "..", "theme", "src", "tokens.css");
|
const theme_token_path = resolve(__dirname, "../theme/src/tokens.css");
|
||||||
|
const version_raw = readFileSync(version_path, { encoding: "utf-8" }).trim();
|
||||||
|
const version = version_raw.replace(/\./g, "-");
|
||||||
|
|
||||||
const version = readFileSync(version_path, { encoding: "utf-8" })
|
const client_version_path = resolve(
|
||||||
.trim()
|
__dirname,
|
||||||
.replace(/\./g, "-");
|
"../../client/python/gradio_client/version.txt"
|
||||||
|
);
|
||||||
|
const client_version_raw = readFileSync(client_version_path, {
|
||||||
|
encoding: "utf-8"
|
||||||
|
}).trim();
|
||||||
|
const client_version = client_version_raw.replace(/\./g, "-");
|
||||||
|
|
||||||
import {
|
import {
|
||||||
inject_ejs,
|
inject_ejs,
|
||||||
@ -36,21 +43,51 @@ export default defineConfig(({ mode }) => {
|
|||||||
const production =
|
const production =
|
||||||
mode === "production:cdn" ||
|
mode === "production:cdn" ||
|
||||||
mode === "production:local" ||
|
mode === "production:local" ||
|
||||||
mode === "production:website";
|
mode === "production:website" ||
|
||||||
|
mode === "production:lite";
|
||||||
const is_cdn = mode === "production:cdn" || mode === "production:website";
|
const is_cdn = mode === "production:cdn" || mode === "production:website";
|
||||||
|
const is_lite = mode.endsWith(":lite");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
base: is_cdn ? CDN_URL : "./",
|
base: is_cdn ? CDN_URL : "./",
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 9876
|
port: 9876,
|
||||||
|
open: is_lite ? "/lite.html" : "/"
|
||||||
},
|
},
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
target: "esnext",
|
target: "esnext",
|
||||||
minify: production,
|
minify: production,
|
||||||
outDir: `../../gradio/templates/${is_cdn ? "cdn" : "frontend"}`
|
outDir: is_lite
|
||||||
|
? resolve(__dirname, "../lite/dist")
|
||||||
|
: `../../gradio/templates/${is_cdn ? "cdn" : "frontend"}`,
|
||||||
|
// To build Gradio-lite as a library, we can't use the library mode
|
||||||
|
// like `lib: is_lite && {}`
|
||||||
|
// because it inevitably enables inlining of all the static file assets,
|
||||||
|
// while we need to disable inlining for the wheel files to pass their URLs to `micropip.install()`.
|
||||||
|
// So we build it as an app and only use the bundled JS and CSS files as library assets, ignoring the HTML file.
|
||||||
|
// See also `lite.ts` about it.
|
||||||
|
rollupOptions: is_lite && {
|
||||||
|
input: "./lite.html",
|
||||||
|
output: {
|
||||||
|
// To use it as a library, we don't add the hash to the file name.
|
||||||
|
entryFileNames: "lite.js",
|
||||||
|
assetFileNames: (file) => {
|
||||||
|
if (file.name?.endsWith(".whl")) {
|
||||||
|
// Python wheel files must follow the naming rules to be installed, so adding a hash to the name is not allowed.
|
||||||
|
return `assets/[name].[ext]`;
|
||||||
|
}
|
||||||
|
if (file.name === "lite.css") {
|
||||||
|
// To use it as a library, we don't add the hash to the file name.
|
||||||
|
return `[name].[ext]`;
|
||||||
|
} else {
|
||||||
|
return `assets/[name]-[hash].[ext]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
define: {
|
define: {
|
||||||
BUILD_MODE: production ? JSON.stringify("prod") : JSON.stringify("dev"),
|
BUILD_MODE: production ? JSON.stringify("prod") : JSON.stringify("dev"),
|
||||||
@ -114,6 +151,20 @@ export default defineConfig(({ mode }) => {
|
|||||||
? ["**/*.node-test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"]
|
? ["**/*.node-test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"]
|
||||||
: ["**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
: ["**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
||||||
globals: true
|
globals: true
|
||||||
}
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
// For the Wasm app to import the wheel file URLs.
|
||||||
|
"gradio.whl": resolve(
|
||||||
|
__dirname,
|
||||||
|
`../../dist/gradio-${version_raw}-py3-none-any.whl`
|
||||||
|
),
|
||||||
|
"gradio_client.whl": resolve(
|
||||||
|
__dirname,
|
||||||
|
`../../client/python/dist/gradio_client-${client_version_raw}-py3-none-any.whl`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
assetsInclude: ["**/*.whl"] // To pass URLs of built wheel files to the Wasm worker.
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
72
js/lite/index.html
Normal file
72
js/lite/index.html
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- A demo HTML file to test the bundled JS and CSS files -->
|
||||||
|
<html
|
||||||
|
lang="en"
|
||||||
|
style="
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<script type="module" crossorigin src="./dist/lite.js"></script>
|
||||||
|
<link rel="stylesheet" href="./dist/lite.css" />
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link
|
||||||
|
rel="preconnect"
|
||||||
|
href="https://fonts.gstatic.com"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
/>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body
|
||||||
|
style="
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div id="gradio-app"></div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.addEventListener("DOMContentLoaded", function () {
|
||||||
|
// <script type="module" /> is loaded asynchronously, so we need to wait for it to load before we can use it.
|
||||||
|
createGradioApp({
|
||||||
|
target: document.getElementById("gradio-app"),
|
||||||
|
pyCode: `
|
||||||
|
import gradio as gr
|
||||||
|
|
||||||
|
def greet(name):
|
||||||
|
return "Hello " + name + "!"
|
||||||
|
|
||||||
|
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
|
||||||
|
|
||||||
|
demo.launch()
|
||||||
|
`,
|
||||||
|
info: true,
|
||||||
|
container: true,
|
||||||
|
isEmbed: false,
|
||||||
|
initialHeight: "300px",
|
||||||
|
eager: false,
|
||||||
|
themeMode: null,
|
||||||
|
autoScroll: false,
|
||||||
|
controlPageTitle: false,
|
||||||
|
appMode: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</html>
|
22
js/wasm/package.json
Normal file
22
js/wasm/package.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "@gradio/wasm",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Gradio Wasm package",
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"private": true,
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"scripts": {
|
||||||
|
"start:client": "tsc -w --incremental",
|
||||||
|
"start:worker": "vite build --config vite.worker.config.js --watch --emptyOutDir=false",
|
||||||
|
"start": "run-p start:*",
|
||||||
|
"build:client": "tsc",
|
||||||
|
"build:worker": "vite build --config vite.worker.config.js",
|
||||||
|
"build": "run-s build:worker build:client"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"pyodide": "^0.23.2"
|
||||||
|
}
|
||||||
|
}
|
1
js/wasm/src/index.ts
Normal file
1
js/wasm/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { WorkerProxy } from "./worker-proxy";
|
62
js/wasm/src/message-types.ts
Normal file
62
js/wasm/src/message-types.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
export interface HttpRequest {
|
||||||
|
method: "GET" | "POST" | "PUT" | "DELETE";
|
||||||
|
path: string;
|
||||||
|
query_string: string;
|
||||||
|
headers: Record<string, string>;
|
||||||
|
body?: Uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HttpResponse {
|
||||||
|
status: number;
|
||||||
|
headers: Record<string, string>;
|
||||||
|
body: Uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InMessageBase {
|
||||||
|
type: string;
|
||||||
|
data: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InMessageInit extends InMessageBase {
|
||||||
|
type: "init";
|
||||||
|
data: {
|
||||||
|
gradioWheelUrl: string;
|
||||||
|
gradioClientWheelUrl: string;
|
||||||
|
requirements: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface InMessageRunPython extends InMessageBase {
|
||||||
|
type: "run-python";
|
||||||
|
data: {
|
||||||
|
code: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface InMessageHttpRequest extends InMessageBase {
|
||||||
|
type: "http-request";
|
||||||
|
data: {
|
||||||
|
request: HttpRequest;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InMessageEcho extends InMessageBase {
|
||||||
|
// For debug
|
||||||
|
type: "echo";
|
||||||
|
data: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InMessage =
|
||||||
|
| InMessageInit
|
||||||
|
| InMessageRunPython
|
||||||
|
| InMessageHttpRequest
|
||||||
|
| InMessageEcho;
|
||||||
|
|
||||||
|
export interface ReplyMessageSuccess<T = unknown> {
|
||||||
|
type: "reply:success";
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
export interface ReplyMessageError {
|
||||||
|
type: "reply:error";
|
||||||
|
error: Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ReplyMessage = ReplyMessageSuccess | ReplyMessageError;
|
2
js/wasm/src/webworker/declarations.d.ts
vendored
Normal file
2
js/wasm/src/webworker/declarations.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Declarations for the WebWorker files where some variables are dynamically loaded through importScript.
|
||||||
|
declare let loadPyodide: any;
|
135
js/wasm/src/webworker/http.ts
Normal file
135
js/wasm/src/webworker/http.ts
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import type { PyProxy } from "pyodide/ffi";
|
||||||
|
import type { HttpRequest, HttpResponse } from "../message-types";
|
||||||
|
|
||||||
|
// Inspired by https://github.com/rstudio/shinylive/blob/v0.1.2/src/messageporthttp.ts
|
||||||
|
|
||||||
|
// A reference to an ASGI application instance in Python
|
||||||
|
// Ref: https://asgi.readthedocs.io/en/latest/specs/main.html#applications
|
||||||
|
type ASGIApplication = (
|
||||||
|
scope: Record<string, unknown>,
|
||||||
|
receive: () => Promise<ReceiveEvent>,
|
||||||
|
send: (event: PyProxy) => Promise<void>
|
||||||
|
) => Promise<void>;
|
||||||
|
|
||||||
|
type ReceiveEvent = RequestReceiveEvent | DisconnectReceiveEvent;
|
||||||
|
// https://asgi.readthedocs.io/en/latest/specs/www.html#request-receive-event
|
||||||
|
interface RequestReceiveEvent {
|
||||||
|
type: "http.request";
|
||||||
|
body?: Uint8Array; // `bytes` in Python
|
||||||
|
more_body: boolean;
|
||||||
|
}
|
||||||
|
// https://asgi.readthedocs.io/en/latest/specs/www.html#disconnect-receive-event
|
||||||
|
interface DisconnectReceiveEvent {
|
||||||
|
type: "http.disconnect";
|
||||||
|
}
|
||||||
|
|
||||||
|
type SendEvent = ResponseStartSendEvent | ResponseBodySendEvent;
|
||||||
|
// https://asgi.readthedocs.io/en/latest/specs/www.html#response-start-send-event
|
||||||
|
interface ResponseStartSendEvent {
|
||||||
|
type: "http.response.start";
|
||||||
|
status: number;
|
||||||
|
headers: Iterable<[Uint8Array, Uint8Array]>;
|
||||||
|
trailers: boolean;
|
||||||
|
}
|
||||||
|
// https://asgi.readthedocs.io/en/latest/specs/www.html#response-body-send-event
|
||||||
|
interface ResponseBodySendEvent {
|
||||||
|
type: "http.response.body";
|
||||||
|
body: Uint8Array; // `bytes` in Python
|
||||||
|
more_body: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function headersToASGI(
|
||||||
|
headers: HttpRequest["headers"]
|
||||||
|
): Array<[string, string]> {
|
||||||
|
const result: Array<[string, string]> = [];
|
||||||
|
for (const [key, value] of Object.entries(headers)) {
|
||||||
|
result.push([key, value]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function uint8ArrayToString(buf: Uint8Array): string {
|
||||||
|
let result = "";
|
||||||
|
for (let i = 0; i < buf.length; i++) {
|
||||||
|
result += String.fromCharCode(buf[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function asgiHeadersToRecord(headers: any): Record<string, string> {
|
||||||
|
headers = headers.map(([key, val]: [Uint8Array, Uint8Array]) => {
|
||||||
|
return [uint8ArrayToString(key), uint8ArrayToString(val)];
|
||||||
|
});
|
||||||
|
return Object.fromEntries(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makeHttpRequest = (
|
||||||
|
asgiApp: ASGIApplication,
|
||||||
|
request: HttpRequest
|
||||||
|
): Promise<HttpResponse> =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
let sent = false;
|
||||||
|
async function receiveFromJs(): Promise<ReceiveEvent> {
|
||||||
|
if (sent) {
|
||||||
|
// NOTE: I implemented this block just referring to the spec. However, it is not reached in practice so it's not combat-proven.
|
||||||
|
return {
|
||||||
|
type: "http.disconnect"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const event: RequestReceiveEvent = {
|
||||||
|
type: "http.request",
|
||||||
|
more_body: false
|
||||||
|
};
|
||||||
|
if (request.body) {
|
||||||
|
event.body = request.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug("receive", event);
|
||||||
|
sent = true;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
let status: number;
|
||||||
|
let headers: { [key: string]: string };
|
||||||
|
let body: Uint8Array = new Uint8Array();
|
||||||
|
async function sendToJs(proxiedEvent: PyProxy): Promise<void> {
|
||||||
|
const event = Object.fromEntries(proxiedEvent.toJs()) as SendEvent;
|
||||||
|
console.debug("send", event);
|
||||||
|
if (event.type === "http.response.start") {
|
||||||
|
status = event.status;
|
||||||
|
headers = asgiHeadersToRecord(event.headers);
|
||||||
|
} else if (event.type === "http.response.body") {
|
||||||
|
body = new Uint8Array([...body, ...event.body]);
|
||||||
|
if (!event.more_body) {
|
||||||
|
const response: HttpResponse = {
|
||||||
|
status,
|
||||||
|
headers,
|
||||||
|
body
|
||||||
|
};
|
||||||
|
console.debug("HTTP response", response);
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unhandled ASGI event: ${JSON.stringify(event)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope
|
||||||
|
const scope = {
|
||||||
|
type: "http",
|
||||||
|
asgi: {
|
||||||
|
version: "3.0",
|
||||||
|
spec_version: "2.1"
|
||||||
|
},
|
||||||
|
http_version: "1.1",
|
||||||
|
scheme: "http",
|
||||||
|
method: request.method,
|
||||||
|
path: request.path,
|
||||||
|
query_string: request.query_string,
|
||||||
|
root_path: "",
|
||||||
|
headers: headersToASGI(request.headers)
|
||||||
|
};
|
||||||
|
|
||||||
|
asgiApp(scope, receiveFromJs, sendToJs);
|
||||||
|
});
|
205
js/wasm/src/webworker/index.ts
Normal file
205
js/wasm/src/webworker/index.ts
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/// <reference lib="webworker" />
|
||||||
|
|
||||||
|
import type { PyodideInterface } from "pyodide";
|
||||||
|
import type {
|
||||||
|
InMessage,
|
||||||
|
ReplyMessageError,
|
||||||
|
ReplyMessageSuccess
|
||||||
|
} from "../message-types";
|
||||||
|
import { makeHttpRequest } from "./http";
|
||||||
|
|
||||||
|
importScripts("https://cdn.jsdelivr.net/pyodide/v0.23.2/full/pyodide.js");
|
||||||
|
|
||||||
|
let pyodide: PyodideInterface;
|
||||||
|
|
||||||
|
let pyodideReadyPromise: undefined | Promise<void> = undefined;
|
||||||
|
|
||||||
|
let call_asgi_app_from_js: (
|
||||||
|
scope: unknown,
|
||||||
|
receive: Function,
|
||||||
|
send: Function
|
||||||
|
) => Promise<void>;
|
||||||
|
|
||||||
|
interface InitOptions {
|
||||||
|
gradioWheelUrl: string;
|
||||||
|
gradioClientWheelUrl: string;
|
||||||
|
requirements: string[];
|
||||||
|
}
|
||||||
|
async function loadPyodideAndPackages(options: InitOptions) {
|
||||||
|
console.debug("Loading Pyodide.");
|
||||||
|
pyodide = await loadPyodide({
|
||||||
|
stdout: console.log,
|
||||||
|
stderr: console.error
|
||||||
|
});
|
||||||
|
console.debug("Pyodide is loaded.");
|
||||||
|
|
||||||
|
console.debug("Loading micropip");
|
||||||
|
await pyodide.loadPackage("micropip");
|
||||||
|
const micropip = pyodide.pyimport("micropip");
|
||||||
|
console.debug("micropip is loaded.");
|
||||||
|
|
||||||
|
const gradioWheelUrls = [
|
||||||
|
options.gradioWheelUrl,
|
||||||
|
options.gradioClientWheelUrl
|
||||||
|
];
|
||||||
|
console.debug("Loading Gradio wheels.", gradioWheelUrls);
|
||||||
|
await micropip.add_mock_package("ffmpy", "0.3.0");
|
||||||
|
await micropip.add_mock_package("orjson", "3.8.12");
|
||||||
|
await micropip.add_mock_package("aiohttp", "3.8.4");
|
||||||
|
await micropip.add_mock_package("multidict", "4.7.6");
|
||||||
|
await pyodide.loadPackage(["ssl", "distutils", "setuptools"]);
|
||||||
|
await micropip.install(["markdown-it-py~=2.2.0"]); // On 3rd June 2023, markdown-it-py 3.0.0 has been released. The `gradio` package depends on its `>=2.0.0` version so its 3.x will be resolved. However, it conflicts with `mdit-py-plugins`'s dependency `markdown-it-py >=1.0.0,<3.0.0` and micropip currently can't resolve it. So we explicitly install the compatible version of the library here.
|
||||||
|
await micropip.install.callKwargs(gradioWheelUrls, {
|
||||||
|
keep_going: true
|
||||||
|
});
|
||||||
|
console.debug("Gradio wheels are loaded.");
|
||||||
|
|
||||||
|
console.debug("Install packages.", options.requirements);
|
||||||
|
await micropip.install.callKwargs(options.requirements, { keep_going: true });
|
||||||
|
console.debug("Packages are installed.");
|
||||||
|
|
||||||
|
console.debug("Mock os module methods.");
|
||||||
|
// `os.link` is used in `aiofiles` (https://github.com/Tinche/aiofiles/blob/v23.1.0/src/aiofiles/os.py#L31),
|
||||||
|
// which is imported from `gradio.ranged_response` (https://github.com/gradio-app/gradio/blob/v3.32.0/gradio/ranged_response.py#L12).
|
||||||
|
// However, it's not available on Wasm.
|
||||||
|
await pyodide.runPythonAsync(`
|
||||||
|
import os
|
||||||
|
|
||||||
|
os.link = lambda src, dst: None
|
||||||
|
`);
|
||||||
|
console.debug("os module methods are mocked.");
|
||||||
|
|
||||||
|
console.debug("Import gradio package.");
|
||||||
|
// Importing the gradio package takes a long time, so we do it separately.
|
||||||
|
// This is necessary for accurate performance profiling.
|
||||||
|
await pyodide.runPythonAsync(`import gradio`);
|
||||||
|
console.debug("gradio package is imported.");
|
||||||
|
|
||||||
|
console.debug("Define a ASGI wrapper function.");
|
||||||
|
// TODO: Unlike Streamlit, user's code is executed in the global scope,
|
||||||
|
// so we should not define this function in the global scope.
|
||||||
|
await pyodide.runPythonAsync(`
|
||||||
|
# Based on Shiny's App.call_pyodide().
|
||||||
|
# https://github.com/rstudio/py-shiny/blob/v0.3.3/shiny/_app.py#L224-L258
|
||||||
|
async def _call_asgi_app_from_js(scope, receive, send):
|
||||||
|
# TODO: Pretty sure there are objects that need to be destroy()'d here?
|
||||||
|
scope = scope.to_py()
|
||||||
|
|
||||||
|
# ASGI requires some values to be byte strings, not character strings. Those are
|
||||||
|
# not that easy to create in JavaScript, so we let the JS side pass us strings
|
||||||
|
# and we convert them to bytes here.
|
||||||
|
if "headers" in scope:
|
||||||
|
# JS doesn't have \`bytes\` so we pass as strings and convert here
|
||||||
|
scope["headers"] = [
|
||||||
|
[value.encode("latin-1") for value in header]
|
||||||
|
for header in scope["headers"]
|
||||||
|
]
|
||||||
|
if "query_string" in scope and scope["query_string"]:
|
||||||
|
scope["query_string"] = scope["query_string"].encode("latin-1")
|
||||||
|
if "raw_path" in scope and scope["raw_path"]:
|
||||||
|
scope["raw_path"] = scope["raw_path"].encode("latin-1")
|
||||||
|
|
||||||
|
async def rcv():
|
||||||
|
event = await receive()
|
||||||
|
return event.to_py()
|
||||||
|
|
||||||
|
async def snd(event):
|
||||||
|
await send(event)
|
||||||
|
|
||||||
|
app = gradio.wasm_utils.get_registered_app()
|
||||||
|
if app is None:
|
||||||
|
raise RuntimeError("Gradio app has not been launched.")
|
||||||
|
|
||||||
|
await app(scope, rcv, snd)
|
||||||
|
`);
|
||||||
|
call_asgi_app_from_js = pyodide.globals.get("_call_asgi_app_from_js");
|
||||||
|
console.debug("The ASGI wrapper function is defined.");
|
||||||
|
|
||||||
|
console.debug("Mock async libraries.");
|
||||||
|
// FastAPI uses `anyio.to_thread.run_sync` internally which, however, doesn't work in Wasm environments where the `threading` module is not supported.
|
||||||
|
// So we mock `anyio.to_thread.run_sync` here not to use threads.
|
||||||
|
await pyodide.runPythonAsync(`
|
||||||
|
async def mocked_anyio_to_thread_run_sync(func, *args, cancellable=False, limiter=None):
|
||||||
|
return func(*args)
|
||||||
|
|
||||||
|
import anyio.to_thread
|
||||||
|
anyio.to_thread.run_sync = mocked_anyio_to_thread_run_sync
|
||||||
|
`);
|
||||||
|
console.debug("Async libraries are mocked.");
|
||||||
|
|
||||||
|
console.debug("Set matplotlib backend.");
|
||||||
|
// Ref: https://github.com/streamlit/streamlit/blob/1.22.0/lib/streamlit/web/bootstrap.py#L111
|
||||||
|
// This backend setting is required to use matplotlib in Wasm environment.
|
||||||
|
await pyodide.runPythonAsync(`
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use("agg")
|
||||||
|
`);
|
||||||
|
console.debug("matplotlib backend is set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.onmessage = async (event: MessageEvent<InMessage>) => {
|
||||||
|
const msg = event.data;
|
||||||
|
console.debug("worker.onmessage", msg);
|
||||||
|
|
||||||
|
const messagePort = event.ports[0];
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (msg.type === "init") {
|
||||||
|
pyodideReadyPromise = loadPyodideAndPackages({
|
||||||
|
gradioWheelUrl: msg.data.gradioWheelUrl,
|
||||||
|
gradioClientWheelUrl: msg.data.gradioClientWheelUrl,
|
||||||
|
requirements: msg.data.requirements
|
||||||
|
});
|
||||||
|
|
||||||
|
const replyMessage: ReplyMessageSuccess = {
|
||||||
|
type: "reply:success",
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
messagePort.postMessage(replyMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pyodideReadyPromise == null) {
|
||||||
|
throw new Error("Pyodide Initialization is not started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
await pyodideReadyPromise;
|
||||||
|
|
||||||
|
switch (msg.type) {
|
||||||
|
case "echo": {
|
||||||
|
const replyMessage: ReplyMessageSuccess = {
|
||||||
|
type: "reply:success",
|
||||||
|
data: msg.data
|
||||||
|
};
|
||||||
|
messagePort.postMessage(replyMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "run-python": {
|
||||||
|
await pyodide.runPythonAsync(msg.data.code);
|
||||||
|
const replyMessage: ReplyMessageSuccess = {
|
||||||
|
type: "reply:success",
|
||||||
|
data: null // We don't send back the execution result because it's not needed for our purpose, and sometimes the result is of type `pyodide.ffi.PyProxy` which cannot be cloned across threads and causes an error.
|
||||||
|
};
|
||||||
|
messagePort.postMessage(replyMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "http-request": {
|
||||||
|
const request = msg.data.request;
|
||||||
|
const response = await makeHttpRequest(call_asgi_app_from_js, request);
|
||||||
|
const replyMessage: ReplyMessageSuccess = {
|
||||||
|
type: "reply:success",
|
||||||
|
data: {
|
||||||
|
response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
messagePort.postMessage(replyMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const replyMessage: ReplyMessageError = {
|
||||||
|
type: "reply:error",
|
||||||
|
error: error as Error
|
||||||
|
};
|
||||||
|
messagePort.postMessage(replyMessage);
|
||||||
|
}
|
||||||
|
};
|
104
js/wasm/src/worker-proxy.ts
Normal file
104
js/wasm/src/worker-proxy.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import type {
|
||||||
|
HttpRequest,
|
||||||
|
HttpResponse,
|
||||||
|
InMessage,
|
||||||
|
ReplyMessage
|
||||||
|
} from "./message-types";
|
||||||
|
|
||||||
|
export interface WorkerProxyOptions {
|
||||||
|
gradioWheelUrl: string;
|
||||||
|
gradioClientWheelUrl: string;
|
||||||
|
requirements: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WorkerProxy {
|
||||||
|
private worker: Worker;
|
||||||
|
|
||||||
|
constructor(options: WorkerProxyOptions) {
|
||||||
|
console.debug("WorkerProxy.constructor(): Create a new worker.");
|
||||||
|
// Loading a worker here relies on Vite's support for WebWorkers (https://vitejs.dev/guide/features.html#web-workers),
|
||||||
|
// assuming that this module is imported from the Gradio frontend (`@gradio/app`), which is bundled with Vite.
|
||||||
|
this.worker = new Worker(new URL("./webworker.js", import.meta.url));
|
||||||
|
|
||||||
|
this.postMessageAsync({
|
||||||
|
type: "init",
|
||||||
|
data: {
|
||||||
|
gradioWheelUrl: options.gradioWheelUrl,
|
||||||
|
gradioClientWheelUrl: options.gradioClientWheelUrl,
|
||||||
|
requirements: options.requirements
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
console.debug("WorkerProxy.constructor(): Initialization is done.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async runPythonAsync(code: string): Promise<void> {
|
||||||
|
await this.postMessageAsync({
|
||||||
|
type: "run-python",
|
||||||
|
data: {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// A wrapper for this.worker.postMessage(). Unlike that function, which
|
||||||
|
// returns void immediately, this function returns a promise, which resolves
|
||||||
|
// when a ReplyMessage is received from the worker.
|
||||||
|
// The original implementation is in https://github.com/rstudio/shinylive/blob/v0.1.2/src/pyodide-proxy.ts#L404-L418
|
||||||
|
private postMessageAsync(msg: InMessage): Promise<unknown> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const channel = new MessageChannel();
|
||||||
|
|
||||||
|
channel.port1.onmessage = (e) => {
|
||||||
|
channel.port1.close();
|
||||||
|
const msg = e.data as ReplyMessage;
|
||||||
|
if (msg.type === "reply:error") {
|
||||||
|
reject(msg.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(msg.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.worker.postMessage(msg, [channel.port2]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async httpRequest(request: HttpRequest): Promise<HttpResponse> {
|
||||||
|
console.debug("WorkerProxy.httpRequest()", request);
|
||||||
|
const result = await this.postMessageAsync({
|
||||||
|
type: "http-request",
|
||||||
|
data: {
|
||||||
|
request
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const response = (result as { response: HttpResponse }).response;
|
||||||
|
|
||||||
|
if (Math.floor(response.status / 100) !== 2) {
|
||||||
|
let bodyText: string;
|
||||||
|
let bodyJson: unknown;
|
||||||
|
try {
|
||||||
|
bodyText = new TextDecoder().decode(response.body);
|
||||||
|
} catch (e) {
|
||||||
|
bodyText = "(failed to decode body)";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
bodyJson = JSON.parse(bodyText);
|
||||||
|
} catch (e) {
|
||||||
|
bodyJson = "(failed to parse body as JSON)";
|
||||||
|
}
|
||||||
|
console.error("Wasm HTTP error", {
|
||||||
|
request,
|
||||||
|
response,
|
||||||
|
bodyText,
|
||||||
|
bodyJson
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public terminate(): void {
|
||||||
|
this.worker.terminate();
|
||||||
|
}
|
||||||
|
}
|
105
js/wasm/tsconfig.json
Normal file
105
js/wasm/tsconfig.json
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||||
|
|
||||||
|
/* Projects */
|
||||||
|
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||||
|
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||||
|
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||||
|
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||||
|
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||||
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||||
|
|
||||||
|
/* Language and Environment */
|
||||||
|
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||||
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||||
|
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
|
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||||
|
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||||
|
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||||
|
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||||
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||||
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||||
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||||
|
|
||||||
|
/* Modules */
|
||||||
|
"module": "ESNext" /* Specify what module code is generated. */,
|
||||||
|
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||||
|
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||||
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||||
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
|
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||||
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||||
|
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||||
|
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||||
|
|
||||||
|
/* JavaScript Support */
|
||||||
|
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||||
|
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||||
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||||
|
|
||||||
|
/* Emit */
|
||||||
|
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
|
||||||
|
"declarationMap": true /* Create sourcemaps for d.ts files. */,
|
||||||
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||||
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||||
|
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||||
|
// "removeComments": true, /* Disable emitting comments. */
|
||||||
|
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||||
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||||
|
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||||
|
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||||
|
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||||
|
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||||
|
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||||
|
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||||
|
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||||
|
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||||
|
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||||
|
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||||
|
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||||
|
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||||
|
|
||||||
|
/* Interop Constraints */
|
||||||
|
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||||
|
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||||
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||||
|
|
||||||
|
/* Type Checking */
|
||||||
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||||
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||||
|
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||||
|
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||||
|
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||||
|
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||||
|
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||||
|
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||||
|
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||||
|
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||||
|
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||||
|
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||||
|
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||||
|
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||||
|
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||||
|
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||||
|
|
||||||
|
/* Completeness */
|
||||||
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||||
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["src/webworker/**/*"] // The worker code is bundled by Vite separately. See its config file.
|
||||||
|
}
|
34
js/wasm/vite.worker.config.js
Normal file
34
js/wasm/vite.worker.config.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import path from "path";
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We bundle the worker file before packaging, while other files are only TS-transpiled.
|
||||||
|
* The consumer of this package, `@gradio/app`, will be bundled with Vite,
|
||||||
|
* and Vite only supports module-type WebWorkers (`new Worker("...", { type: "module" })`) to handle `import` in the worker file,
|
||||||
|
* because in the dev mode it doesn't bundle the worker file and just relies on the browser's native support for module-type workers to resolve the imports.
|
||||||
|
* However, we need to use `importScripts()` in the worker to load Pyodide from the CDN, which is only supported by classic WebWorkers (`new Worker("...")`),
|
||||||
|
* while we still want to use `import` in the worker to modularize the code.
|
||||||
|
* So, we bundle the worker file to resolve `import`s here before exporting, preserving `importScripts()` in the bundled file,
|
||||||
|
* and load the bundled worker file on `@gradio/app` as a classic WebWorker.
|
||||||
|
*
|
||||||
|
* Note: We tried the following approaches, but they failed:
|
||||||
|
* 1. Just TS-transpile the worker file like other files into `worker.js`, and use it like `new Worker("worker.js")`.
|
||||||
|
* It failed because `tsc` reserves `importScripts()` and also appends `export {};` to the end of the file to specify it as a module (`https://github.com/microsoft/TypeScript/issues/41513`),
|
||||||
|
* however, `importScripts()` is only supported by classic WebWorkers, and `export {};` is not supported by classic WebWorkers.
|
||||||
|
* 2. Use ESM import instead of `importScripts()`, which is (experimentally?) supported by Pyodide since v0.20.0 (https://pyodide.org/en/stable/project/changelog.html#javascript-package),
|
||||||
|
* using `import { loadPyodide } from "https://cdn.jsdelivr.net/pyodide/v0.23.2/full/pyodide.js";` in the worker file, instead of `importScripts(...)`.
|
||||||
|
* It was successful in the dev mode, but failed in the prod mode, which has this problem: https://github.com/pyodide/pyodide/issues/2217#issuecomment-1328344562.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
outDir: "dist",
|
||||||
|
rollupOptions: {
|
||||||
|
input: path.join(__dirname, "src/webworker/index.ts"),
|
||||||
|
// Ref: https://github.com/rollup/rollup/issues/2616#issuecomment-1431551704
|
||||||
|
output: {
|
||||||
|
entryFileNames: "webworker.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
215
pnpm-lock.yaml
215
pnpm-lock.yaml
@ -46,10 +46,10 @@ importers:
|
|||||||
version: 20.3.1
|
version: 20.3.1
|
||||||
'@typescript-eslint/eslint-plugin':
|
'@typescript-eslint/eslint-plugin':
|
||||||
specifier: ^5.60.0
|
specifier: ^5.60.0
|
||||||
version: 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3)
|
version: 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.0.4)
|
||||||
'@typescript-eslint/parser':
|
'@typescript-eslint/parser':
|
||||||
specifier: ^5.60.0
|
specifier: ^5.60.0
|
||||||
version: 5.60.0(eslint@8.43.0)(typescript@5.1.3)
|
version: 5.60.0(eslint@8.43.0)(typescript@5.0.4)
|
||||||
autoprefixer:
|
autoprefixer:
|
||||||
specifier: ^10.4.4
|
specifier: ^10.4.4
|
||||||
version: 10.4.4(postcss@8.4.6)
|
version: 10.4.4(postcss@8.4.6)
|
||||||
@ -76,7 +76,7 @@ importers:
|
|||||||
version: 4.1.5
|
version: 4.1.5
|
||||||
msw:
|
msw:
|
||||||
specifier: ^1.0.0
|
specifier: ^1.0.0
|
||||||
version: 1.0.0(typescript@5.1.3)
|
version: 1.0.0(typescript@5.0.4)
|
||||||
node-html-parser:
|
node-html-parser:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.0
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
@ -133,16 +133,16 @@ importers:
|
|||||||
version: 3.6.0(svelte@3.59.1)
|
version: 3.6.0(svelte@3.59.1)
|
||||||
svelte-preprocess:
|
svelte-preprocess:
|
||||||
specifier: ^5.0.3
|
specifier: ^5.0.3
|
||||||
version: 5.0.3(postcss@8.4.6)(svelte@3.59.1)(typescript@5.1.3)
|
version: 5.0.3(postcss@8.4.6)(svelte@3.59.1)(typescript@5.0.4)
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^3.1.6
|
specifier: ^3.1.6
|
||||||
version: 3.1.6(postcss@8.4.6)
|
version: 3.1.6(postcss@8.4.6)
|
||||||
tinyspy:
|
tinyspy:
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.1.1
|
version: 2.0.0
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.1.3
|
version: 5.0.4
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.9
|
specifier: ^4.3.9
|
||||||
version: 4.3.9(@types/node@20.3.1)
|
version: 4.3.9(@types/node@20.3.1)
|
||||||
@ -301,6 +301,9 @@ importers:
|
|||||||
'@gradio/video':
|
'@gradio/video':
|
||||||
specifier: workspace:^0.0.1
|
specifier: workspace:^0.0.1
|
||||||
version: link:../video
|
version: link:../video
|
||||||
|
'@gradio/wasm':
|
||||||
|
specifier: workspace:^0.0.1
|
||||||
|
version: link:../wasm
|
||||||
'@playwright/test':
|
'@playwright/test':
|
||||||
specifier: ^1.35.1
|
specifier: ^1.35.1
|
||||||
version: 1.35.1
|
version: 1.35.1
|
||||||
@ -723,6 +726,12 @@ importers:
|
|||||||
specifier: workspace:^0.0.1
|
specifier: workspace:^0.0.1
|
||||||
version: link:../upload
|
version: link:../upload
|
||||||
|
|
||||||
|
js/wasm:
|
||||||
|
devDependencies:
|
||||||
|
pyodide:
|
||||||
|
specifier: ^0.23.2
|
||||||
|
version: 0.23.2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
/@adobe/css-tools@4.2.0:
|
/@adobe/css-tools@4.2.0:
|
||||||
@ -1548,13 +1557,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==}
|
resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/intl-localematcher': 0.2.25
|
'@formatjs/intl-localematcher': 0.2.25
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@formatjs/fast-memoize@1.2.1:
|
/@formatjs/fast-memoize@1.2.1:
|
||||||
resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==}
|
resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@formatjs/icu-messageformat-parser@2.1.0:
|
/@formatjs/icu-messageformat-parser@2.1.0:
|
||||||
@ -1562,20 +1571,20 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/ecma402-abstract': 1.11.4
|
'@formatjs/ecma402-abstract': 1.11.4
|
||||||
'@formatjs/icu-skeleton-parser': 1.3.6
|
'@formatjs/icu-skeleton-parser': 1.3.6
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@formatjs/icu-skeleton-parser@1.3.6:
|
/@formatjs/icu-skeleton-parser@1.3.6:
|
||||||
resolution: {integrity: sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==}
|
resolution: {integrity: sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/ecma402-abstract': 1.11.4
|
'@formatjs/ecma402-abstract': 1.11.4
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@formatjs/intl-localematcher@0.2.25:
|
/@formatjs/intl-localematcher@0.2.25:
|
||||||
resolution: {integrity: sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==}
|
resolution: {integrity: sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@humanwhocodes/config-array@0.11.10:
|
/@humanwhocodes/config-array@0.11.10:
|
||||||
@ -2184,7 +2193,7 @@ packages:
|
|||||||
'@types/yargs-parser': 21.0.0
|
'@types/yargs-parser': 21.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/eslint-plugin@5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.1.3):
|
/@typescript-eslint/eslint-plugin@5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==}
|
resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2196,23 +2205,23 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.5.1
|
'@eslint-community/regexpp': 4.5.1
|
||||||
'@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.1.3)
|
'@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.0.4)
|
||||||
'@typescript-eslint/scope-manager': 5.60.0
|
'@typescript-eslint/scope-manager': 5.60.0
|
||||||
'@typescript-eslint/type-utils': 5.60.0(eslint@8.43.0)(typescript@5.1.3)
|
'@typescript-eslint/type-utils': 5.60.0(eslint@8.43.0)(typescript@5.0.4)
|
||||||
'@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.1.3)
|
'@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.0.4)
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.43.0
|
eslint: 8.43.0
|
||||||
grapheme-splitter: 1.0.4
|
grapheme-splitter: 1.0.4
|
||||||
ignore: 5.2.4
|
ignore: 5.2.4
|
||||||
natural-compare-lite: 1.4.0
|
natural-compare-lite: 1.4.0
|
||||||
semver: 7.3.8
|
semver: 7.3.8
|
||||||
tsutils: 3.21.0(typescript@5.1.3)
|
tsutils: 3.21.0(typescript@5.0.4)
|
||||||
typescript: 5.1.3
|
typescript: 5.0.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/parser@5.60.0(eslint@8.43.0)(typescript@5.1.3):
|
/@typescript-eslint/parser@5.60.0(eslint@8.43.0)(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==}
|
resolution: {integrity: sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2224,10 +2233,10 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 5.60.0
|
'@typescript-eslint/scope-manager': 5.60.0
|
||||||
'@typescript-eslint/types': 5.60.0
|
'@typescript-eslint/types': 5.60.0
|
||||||
'@typescript-eslint/typescript-estree': 5.60.0(typescript@5.1.3)
|
'@typescript-eslint/typescript-estree': 5.60.0(typescript@5.0.4)
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.43.0
|
eslint: 8.43.0
|
||||||
typescript: 5.1.3
|
typescript: 5.0.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
@ -2240,7 +2249,7 @@ packages:
|
|||||||
'@typescript-eslint/visitor-keys': 5.60.0
|
'@typescript-eslint/visitor-keys': 5.60.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/type-utils@5.60.0(eslint@8.43.0)(typescript@5.1.3):
|
/@typescript-eslint/type-utils@5.60.0(eslint@8.43.0)(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==}
|
resolution: {integrity: sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2250,12 +2259,12 @@ packages:
|
|||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 5.60.0(typescript@5.1.3)
|
'@typescript-eslint/typescript-estree': 5.60.0(typescript@5.0.4)
|
||||||
'@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.1.3)
|
'@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.0.4)
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.43.0
|
eslint: 8.43.0
|
||||||
tsutils: 3.21.0(typescript@5.1.3)
|
tsutils: 3.21.0(typescript@5.0.4)
|
||||||
typescript: 5.1.3
|
typescript: 5.0.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
@ -2265,7 +2274,7 @@ packages:
|
|||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/typescript-estree@5.60.0(typescript@5.1.3):
|
/@typescript-eslint/typescript-estree@5.60.0(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==}
|
resolution: {integrity: sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2280,13 +2289,13 @@ packages:
|
|||||||
globby: 11.1.0
|
globby: 11.1.0
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
semver: 7.3.8
|
semver: 7.3.8
|
||||||
tsutils: 3.21.0(typescript@5.1.3)
|
tsutils: 3.21.0(typescript@5.0.4)
|
||||||
typescript: 5.1.3
|
typescript: 5.0.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/utils@5.60.0(eslint@8.43.0)(typescript@5.1.3):
|
/@typescript-eslint/utils@5.60.0(eslint@8.43.0)(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==}
|
resolution: {integrity: sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2297,7 +2306,7 @@ packages:
|
|||||||
'@types/semver': 7.5.0
|
'@types/semver': 7.5.0
|
||||||
'@typescript-eslint/scope-manager': 5.60.0
|
'@typescript-eslint/scope-manager': 5.60.0
|
||||||
'@typescript-eslint/types': 5.60.0
|
'@typescript-eslint/types': 5.60.0
|
||||||
'@typescript-eslint/typescript-estree': 5.60.0(typescript@5.1.3)
|
'@typescript-eslint/typescript-estree': 5.60.0(typescript@5.0.4)
|
||||||
eslint: 8.43.0
|
eslint: 8.43.0
|
||||||
eslint-scope: 5.1.1
|
eslint-scope: 5.1.1
|
||||||
semver: 7.3.8
|
semver: 7.3.8
|
||||||
@ -2534,7 +2543,7 @@ packages:
|
|||||||
engines: {node: '>=12.20.1'}
|
engines: {node: '>=12.20.1'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/autoprefixer@10.4.4(postcss@8.4.6):
|
/autoprefixer@10.4.4(postcss@8.4.6):
|
||||||
@ -2592,6 +2601,10 @@ packages:
|
|||||||
/balanced-match@1.0.2:
|
/balanced-match@1.0.2:
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||||
|
|
||||||
|
/base-64@1.0.0:
|
||||||
|
resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/base64-js@1.5.1:
|
/base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -2646,7 +2659,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
fast-unique-numbers: 6.0.21
|
fast-unique-numbers: 6.0.21
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
worker-factory: 6.0.69
|
worker-factory: 6.0.69
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -2678,7 +2691,6 @@ packages:
|
|||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
node-gyp-build: 4.6.0
|
node-gyp-build: 4.6.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/busboy@1.6.0:
|
/busboy@1.6.0:
|
||||||
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
|
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
|
||||||
@ -2955,7 +2967,7 @@ packages:
|
|||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
dashify: 2.0.0
|
dashify: 2.0.0
|
||||||
indefinite-article: 0.0.2
|
indefinite-article: 0.0.2
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/concat-map@0.0.1:
|
/concat-map@0.0.1:
|
||||||
@ -2971,7 +2983,7 @@ packages:
|
|||||||
js-string-escape: 1.0.1
|
js-string-escape: 1.0.1
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
md5-hex: 3.0.1
|
md5-hex: 3.0.1
|
||||||
semver: 7.4.0
|
semver: 7.3.8
|
||||||
well-known-symbols: 2.0.0
|
well-known-symbols: 2.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -3938,7 +3950,7 @@ packages:
|
|||||||
engines: {node: '>=12.20.1'}
|
engines: {node: '>=12.20.1'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/fastq@1.13.0:
|
/fastq@1.13.0:
|
||||||
@ -4131,7 +4143,7 @@ packages:
|
|||||||
fs.realpath: 1.0.0
|
fs.realpath: 1.0.0
|
||||||
inflight: 1.0.6
|
inflight: 1.0.6
|
||||||
inherits: 2.0.4
|
inherits: 2.0.4
|
||||||
minimatch: 3.1.2
|
minimatch: 3.0.4
|
||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
path-is-absolute: 1.0.1
|
path-is-absolute: 1.0.1
|
||||||
|
|
||||||
@ -4394,7 +4406,7 @@ packages:
|
|||||||
'@formatjs/ecma402-abstract': 1.11.4
|
'@formatjs/ecma402-abstract': 1.11.4
|
||||||
'@formatjs/fast-memoize': 1.2.1
|
'@formatjs/fast-memoize': 1.2.1
|
||||||
'@formatjs/icu-messageformat-parser': 2.1.0
|
'@formatjs/icu-messageformat-parser': 2.1.0
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/is-arguments@1.1.1:
|
/is-arguments@1.1.1:
|
||||||
@ -4717,7 +4729,7 @@ packages:
|
|||||||
whatwg-encoding: 2.0.0
|
whatwg-encoding: 2.0.0
|
||||||
whatwg-mimetype: 3.0.0
|
whatwg-mimetype: 3.0.0
|
||||||
whatwg-url: 12.0.1
|
whatwg-url: 12.0.1
|
||||||
ws: 8.13.0
|
ws: 8.13.0(bufferutil@4.0.7)
|
||||||
xml-name-validator: 4.0.0
|
xml-name-validator: 4.0.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
- bufferutil
|
||||||
@ -4950,7 +4962,7 @@ packages:
|
|||||||
broker-factory: 3.0.68
|
broker-factory: 3.0.68
|
||||||
fast-unique-numbers: 6.0.21
|
fast-unique-numbers: 6.0.21
|
||||||
media-encoder-host-worker: 9.0.70
|
media-encoder-host-worker: 9.0.70
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/media-encoder-host-worker@9.0.70:
|
/media-encoder-host-worker@9.0.70:
|
||||||
@ -4958,7 +4970,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
extendable-media-recorder-wav-encoder-broker: 7.0.70
|
extendable-media-recorder-wav-encoder-broker: 7.0.70
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
worker-factory: 6.0.69
|
worker-factory: 6.0.69
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -4968,7 +4980,7 @@ packages:
|
|||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
media-encoder-host-broker: 7.0.70
|
media-encoder-host-broker: 7.0.70
|
||||||
media-encoder-host-worker: 9.0.70
|
media-encoder-host-worker: 9.0.70
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/memoizee@0.4.15:
|
/memoizee@0.4.15:
|
||||||
@ -5053,12 +5065,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==}
|
resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion: 1.1.11
|
brace-expansion: 1.1.11
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minimatch@3.1.2:
|
/minimatch@3.1.2:
|
||||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion: 1.1.11
|
brace-expansion: 1.1.11
|
||||||
|
dev: false
|
||||||
|
|
||||||
/minimist-options@4.1.0:
|
/minimist-options@4.1.0:
|
||||||
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
|
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
|
||||||
@ -5103,7 +5115,7 @@ packages:
|
|||||||
/ms@2.1.2:
|
/ms@2.1.2:
|
||||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||||
|
|
||||||
/msw@1.0.0(typescript@5.1.3):
|
/msw@1.0.0(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-8QVa1RAN/Nzbn/tKmtimJ+b2M1QZOMdETQW7/1TmBOZ4w+wJojfxuh1Hj5J4FYdBgZWW/TK4CABUOlOM4OjTOA==}
|
resolution: {integrity: sha512-8QVa1RAN/Nzbn/tKmtimJ+b2M1QZOMdETQW7/1TmBOZ4w+wJojfxuh1Hj5J4FYdBgZWW/TK4CABUOlOM4OjTOA==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@ -5132,7 +5144,7 @@ packages:
|
|||||||
path-to-regexp: 6.2.1
|
path-to-regexp: 6.2.1
|
||||||
strict-event-emitter: 0.4.6
|
strict-event-emitter: 0.4.6
|
||||||
type-fest: 2.19.0
|
type-fest: 2.19.0
|
||||||
typescript: 5.1.3
|
typescript: 5.0.4
|
||||||
yargs: 17.6.2
|
yargs: 17.6.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
@ -5144,7 +5156,7 @@ packages:
|
|||||||
engines: {node: '>=12.20.1'}
|
engines: {node: '>=12.20.1'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/mute-stream@0.0.8:
|
/mute-stream@0.0.8:
|
||||||
@ -5193,12 +5205,10 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/node-gyp-build@4.6.0:
|
/node-gyp-build@4.6.0:
|
||||||
resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==}
|
resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: false
|
|
||||||
|
|
||||||
/node-html-parser@6.0.0:
|
/node-html-parser@6.0.0:
|
||||||
resolution: {integrity: sha512-o4vS5Jm7ZdV5WN4/jHmCEVJOpm4exLCeXOcZnNzXi0BGv0AS8FsGwyQ4k0Ujmui1NMQs6qsTy+amjjpr9rmz4Q==}
|
resolution: {integrity: sha512-o4vS5Jm7ZdV5WN4/jHmCEVJOpm4exLCeXOcZnNzXi0BGv0AS8FsGwyQ4k0Ujmui1NMQs6qsTy+amjjpr9rmz4Q==}
|
||||||
@ -5848,6 +5858,18 @@ packages:
|
|||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/pyodide@0.23.2:
|
||||||
|
resolution: {integrity: sha512-GK4YDZVgzfAXK/7X0IiCI+142k0Ah/HwYTzDHtG8zC47dflWYuPozeFbOngShuL1M9Un5sCmHFqiH3boxJv0pQ==}
|
||||||
|
dependencies:
|
||||||
|
base-64: 1.0.0
|
||||||
|
node-fetch: 2.6.7
|
||||||
|
ws: 8.13.0(bufferutil@4.0.7)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- bufferutil
|
||||||
|
- encoding
|
||||||
|
- utf-8-validate
|
||||||
|
dev: true
|
||||||
|
|
||||||
/querystringify@2.2.0:
|
/querystringify@2.2.0:
|
||||||
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -5936,7 +5958,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-5QTJKukH8JcQR1f2FqZsQ1QD2aoc6/+tM0WPv8sqEI4THzbiMfH4VuWF3BfdL2F9mRjLo81nFC9OShCj87wMhg==}
|
resolution: {integrity: sha512-5QTJKukH8JcQR1f2FqZsQ1QD2aoc6/+tM0WPv8sqEI4THzbiMfH4VuWF3BfdL2F9mRjLo81nFC9OShCj87wMhg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/recorder-audio-worklet@5.1.29:
|
/recorder-audio-worklet@5.1.29:
|
||||||
@ -5948,7 +5970,7 @@ packages:
|
|||||||
recorder-audio-worklet-processor: 4.2.15
|
recorder-audio-worklet-processor: 4.2.15
|
||||||
standardized-audio-context: 25.3.32
|
standardized-audio-context: 25.3.32
|
||||||
subscribable-things: 2.1.7
|
subscribable-things: 2.1.7
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
worker-factory: 6.0.69
|
worker-factory: 6.0.69
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -6074,7 +6096,7 @@ packages:
|
|||||||
/rxjs@7.8.0:
|
/rxjs@7.8.0:
|
||||||
resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==}
|
resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/sade@1.8.1:
|
/sade@1.8.1:
|
||||||
@ -6299,7 +6321,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
automation-events: 4.0.21
|
automation-events: 4.0.21
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/std-env@3.3.2:
|
/std-env@3.3.2:
|
||||||
@ -6428,7 +6450,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
rxjs-interop: 2.0.0
|
rxjs-interop: 2.0.0
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/supports-color@5.5.0:
|
/supports-color@5.5.0:
|
||||||
@ -6651,7 +6673,7 @@ packages:
|
|||||||
typescript: 4.9.5
|
typescript: 4.9.5
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/svelte-preprocess@5.0.3(postcss@8.4.6)(svelte@3.59.1)(typescript@5.1.3):
|
/svelte-preprocess@5.0.3(postcss@8.4.6)(svelte@3.59.1)(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-GrHF1rusdJVbOZOwgPWtpqmaexkydznKzy5qIC2FabgpFyKN57bjMUUUqPRfbBXK5igiEWn1uO/DXsa2vJ5VHA==}
|
resolution: {integrity: sha512-GrHF1rusdJVbOZOwgPWtpqmaexkydznKzy5qIC2FabgpFyKN57bjMUUUqPRfbBXK5igiEWn1uO/DXsa2vJ5VHA==}
|
||||||
engines: {node: '>= 14.10.0'}
|
engines: {node: '>= 14.10.0'}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
@ -6696,7 +6718,7 @@ packages:
|
|||||||
sorcery: 0.11.0
|
sorcery: 0.11.0
|
||||||
strip-indent: 3.0.0
|
strip-indent: 3.0.0
|
||||||
svelte: 3.59.1
|
svelte: 3.59.1
|
||||||
typescript: 5.1.3
|
typescript: 5.0.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/svelte-range-slider-pips@2.0.2:
|
/svelte-range-slider-pips@2.0.2:
|
||||||
@ -6813,6 +6835,11 @@ packages:
|
|||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/tinyspy@2.0.0:
|
||||||
|
resolution: {integrity: sha512-B9wP6IgqmgNTDffygA716cr+PrW51LZc22qFs7+Aur0t73gqf3vNwwlwdcnE1AcqusK6V4R4+5jQ69nIQDiJiw==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tinyspy@2.1.1:
|
/tinyspy@2.1.1:
|
||||||
resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==}
|
resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -6854,7 +6881,6 @@ packages:
|
|||||||
|
|
||||||
/tr46@0.0.3:
|
/tr46@0.0.3:
|
||||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/tr46@4.1.1:
|
/tr46@4.1.1:
|
||||||
resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==}
|
resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==}
|
||||||
@ -6887,14 +6913,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==}
|
resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/tsutils@3.21.0(typescript@5.1.3):
|
/tsutils@3.21.0(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
peerDependencies:
|
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'
|
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 1.14.1
|
tslib: 1.14.1
|
||||||
typescript: 5.1.3
|
typescript: 5.0.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/tty-table@4.2.1:
|
/tty-table@4.2.1:
|
||||||
@ -6978,13 +7004,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==}
|
resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==}
|
||||||
engines: {node: '>=12.20'}
|
engines: {node: '>=12.20'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
|
||||||
|
|
||||||
/typescript@5.1.3:
|
|
||||||
resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==}
|
|
||||||
engines: {node: '>=14.17'}
|
|
||||||
hasBin: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ufo@1.1.1:
|
/ufo@1.1.1:
|
||||||
resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==}
|
resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==}
|
||||||
@ -7068,7 +7087,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
d3-array: 3.1.1
|
d3-array: 3.1.1
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7078,7 +7097,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
vega-format: 1.1.0
|
vega-format: 1.1.0
|
||||||
vega-loader: 4.5.0
|
vega-loader: 4.5.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7110,7 +7129,7 @@ packages:
|
|||||||
d3-interpolate: 3.0.1
|
d3-interpolate: 3.0.1
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-scale: 7.2.0
|
vega-scale: 7.2.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7123,7 +7142,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-y5+c2frq0tGwJ7vYXzZcfVcIRF/QGfhf2e+bV1Z0iQs+M2lI1II1GPDdmOcMKimpoCVp/D61KUJDIGE1DSmk2w==}
|
resolution: {integrity: sha512-y5+c2frq0tGwJ7vYXzZcfVcIRF/QGfhf2e+bV1Z0iQs+M2lI1II1GPDdmOcMKimpoCVp/D61KUJDIGE1DSmk2w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 0.0.50
|
'@types/estree': 0.0.50
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vega-force@4.1.0:
|
/vega-force@4.1.0:
|
||||||
@ -7131,7 +7150,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
d3-force: 3.0.0
|
d3-force: 3.0.0
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7143,7 +7162,7 @@ packages:
|
|||||||
d3-format: 3.1.0
|
d3-format: 3.1.0
|
||||||
d3-time-format: 4.1.0
|
d3-time-format: 4.1.0
|
||||||
vega-time: 2.1.0
|
vega-time: 2.1.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vega-functions@5.13.0:
|
/vega-functions@5.13.0:
|
||||||
@ -7159,7 +7178,7 @@ packages:
|
|||||||
vega-selections: 5.4.0
|
vega-selections: 5.4.0
|
||||||
vega-statistics: 1.8.0
|
vega-statistics: 1.8.0
|
||||||
vega-time: 2.1.0
|
vega-time: 2.1.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7174,7 +7193,7 @@ packages:
|
|||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-projection: 1.5.0
|
vega-projection: 1.5.0
|
||||||
vega-statistics: 1.8.0
|
vega-statistics: 1.8.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7184,7 +7203,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
d3-hierarchy: 3.1.2
|
d3-hierarchy: 3.1.2
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7199,7 +7218,7 @@ packages:
|
|||||||
vega-canvas: 1.2.6
|
vega-canvas: 1.2.6
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-scenegraph: 4.10.1
|
vega-scenegraph: 4.10.1
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7231,7 +7250,7 @@ packages:
|
|||||||
node-fetch: 2.6.7
|
node-fetch: 2.6.7
|
||||||
topojson-client: 3.1.0
|
topojson-client: 3.1.0
|
||||||
vega-format: 1.1.0
|
vega-format: 1.1.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7243,7 +7262,7 @@ packages:
|
|||||||
vega-event-selector: 3.0.0
|
vega-event-selector: 3.0.0
|
||||||
vega-functions: 5.13.0
|
vega-functions: 5.13.0
|
||||||
vega-scale: 7.2.0
|
vega-scale: 7.2.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7261,7 +7280,7 @@ packages:
|
|||||||
d3-array: 3.1.1
|
d3-array: 3.1.1
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-statistics: 1.8.0
|
vega-statistics: 1.8.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7270,7 +7289,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-gE+sO2IfxMUpV0RkFeQVnHdmPy3K7LjHakISZgUGsDI/ZFs9y+HhBf8KTGSL5pcZPtQsZh3GBQ0UonqL1mp9PA==}
|
resolution: {integrity: sha512-gE+sO2IfxMUpV0RkFeQVnHdmPy3K7LjHakISZgUGsDI/ZFs9y+HhBf8KTGSL5pcZPtQsZh3GBQ0UonqL1mp9PA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7282,7 +7301,7 @@ packages:
|
|||||||
d3-interpolate: 3.0.1
|
d3-interpolate: 3.0.1
|
||||||
d3-scale: 4.0.2
|
d3-scale: 4.0.2
|
||||||
vega-time: 2.1.0
|
vega-time: 2.1.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vega-scenegraph@4.10.1:
|
/vega-scenegraph@4.10.1:
|
||||||
@ -7293,7 +7312,7 @@ packages:
|
|||||||
vega-canvas: 1.2.6
|
vega-canvas: 1.2.6
|
||||||
vega-loader: 4.5.0
|
vega-loader: 4.5.0
|
||||||
vega-scale: 7.2.0
|
vega-scale: 7.2.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7307,7 +7326,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
d3-array: 3.1.1
|
d3-array: 3.1.1
|
||||||
vega-expression: 5.0.0
|
vega-expression: 5.0.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vega-statistics@1.8.0:
|
/vega-statistics@1.8.0:
|
||||||
@ -7331,7 +7350,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
d3-array: 3.1.1
|
d3-array: 3.1.1
|
||||||
d3-time: 3.0.0
|
d3-time: 3.0.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vega-tooltip@0.32.0:
|
/vega-tooltip@0.32.0:
|
||||||
@ -7347,7 +7366,7 @@ packages:
|
|||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-statistics: 1.8.0
|
vega-statistics: 1.8.0
|
||||||
vega-time: 2.1.0
|
vega-time: 2.1.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7357,7 +7376,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
vega-event-selector: 3.0.0
|
vega-event-selector: 3.0.0
|
||||||
vega-expression: 5.0.0
|
vega-expression: 5.0.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vega-util@1.17.0:
|
/vega-util@1.17.0:
|
||||||
@ -7373,7 +7392,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-scenegraph: 4.10.1
|
vega-scenegraph: 4.10.1
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7388,7 +7407,7 @@ packages:
|
|||||||
vega-functions: 5.13.0
|
vega-functions: 5.13.0
|
||||||
vega-runtime: 6.1.3
|
vega-runtime: 6.1.3
|
||||||
vega-scenegraph: 4.10.1
|
vega-scenegraph: 4.10.1
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7398,7 +7417,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
d3-delaunay: 6.0.2
|
d3-delaunay: 6.0.2
|
||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7410,7 +7429,7 @@ packages:
|
|||||||
vega-dataflow: 5.7.4
|
vega-dataflow: 5.7.4
|
||||||
vega-scale: 7.2.0
|
vega-scale: 7.2.0
|
||||||
vega-statistics: 1.8.0
|
vega-statistics: 1.8.0
|
||||||
vega-util: 1.17.2
|
vega-util: 1.17.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
@ -7651,7 +7670,6 @@ packages:
|
|||||||
|
|
||||||
/webidl-conversions@3.0.1:
|
/webidl-conversions@3.0.1:
|
||||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/webidl-conversions@7.0.0:
|
/webidl-conversions@7.0.0:
|
||||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||||
@ -7688,7 +7706,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tr46: 0.0.3
|
tr46: 0.0.3
|
||||||
webidl-conversions: 3.0.1
|
webidl-conversions: 3.0.1
|
||||||
dev: false
|
|
||||||
|
|
||||||
/which-boxed-primitive@1.0.2:
|
/which-boxed-primitive@1.0.2:
|
||||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||||
@ -7759,7 +7776,7 @@ packages:
|
|||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
compilerr: 9.0.21
|
compilerr: 9.0.21
|
||||||
fast-unique-numbers: 6.0.21
|
fast-unique-numbers: 6.0.21
|
||||||
tslib: 2.5.3
|
tslib: 2.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/wrap-ansi@6.2.0:
|
/wrap-ansi@6.2.0:
|
||||||
@ -7783,19 +7800,6 @@ packages:
|
|||||||
/wrappy@1.0.2:
|
/wrappy@1.0.2:
|
||||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||||
|
|
||||||
/ws@8.13.0:
|
|
||||||
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
bufferutil: ^4.0.1
|
|
||||||
utf-8-validate: '>=5.0.2'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
bufferutil:
|
|
||||||
optional: true
|
|
||||||
utf-8-validate:
|
|
||||||
optional: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ws@8.13.0(bufferutil@4.0.7):
|
/ws@8.13.0(bufferutil@4.0.7):
|
||||||
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
|
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
@ -7809,7 +7813,6 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
bufferutil: 4.0.7
|
bufferutil: 4.0.7
|
||||||
dev: false
|
|
||||||
|
|
||||||
/xml-name-validator@4.0.0:
|
/xml-name-validator@4.0.0:
|
||||||
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
packages:
|
packages:
|
||||||
- 'js/*'
|
- 'js/*'
|
||||||
- 'client/js'
|
- 'client/js'
|
||||||
|
Loading…
Reference in New Issue
Block a user