From fe057300f0672c62dab9d9b4501054ac5d45a4ec Mon Sep 17 00:00:00 2001 From: pngwn Date: Wed, 23 Aug 2023 21:48:10 +0100 Subject: [PATCH] delegate gradio events via a custom event dispatcher (#5279) * delegate gradio events via a custom event dispatcher * improve md perf + share code * fix df markdown * prevent model3d from rerending too frequently * tweaks * fix more event bugs with video * add changeset * optimise handle mount * does this do anything * fix * remove old dispatches * fix dropdown position * oops * fixes * fix tests * fix types * format * fix markdown code * add changeset * fix typecheck * fix typecheck * fix demos * notebooks * fix tests * changer * maybe this * fixes * add changeset * fix chatbot alignment mobile * fix chantbot * add changeset * changeset * changeset * storybook --------- Co-authored-by: gradio-pr-bot Co-authored-by: Abubakar Abid --- .changeset/chilly-chefs-hug.md | 56 + demo/event_trigger/run.ipynb | 2 +- demo/event_trigger/run.py | 4 + demo/latex/run.ipynb | 2 +- demo/latex/run.py | 3 +- demo/markdown_example/run.ipynb | 2 +- demo/markdown_example/run.py | 17 + js/_website/src/lib/assets/prism.css | 1 - .../static/AnnotatedImage.svelte | 24 +- js/app/package.json | 1 - js/app/src/Blocks.svelte | 164 ++- js/app/src/Index.svelte | 15 +- js/app/src/Login.svelte | 2 +- js/app/src/MountComponents.svelte | 30 + js/app/src/Render.svelte | 3 + js/app/src/components/Dataset/Dataset.svelte | 15 +- js/app/src/css.ts | 3 +- js/app/src/gradio_helper.ts | 33 + js/app/test/components.test.ts | 24 +- js/atoms/src/ShareButton.svelte | 2 +- js/atoms/src/UploadText.svelte | 2 +- js/audio/interactive/Audio.svelte | 10 +- js/audio/interactive/InteractiveAudio.svelte | 43 +- js/audio/static/AudioPlayer.svelte | 2 +- js/audio/static/StaticAudio.svelte | 19 +- js/button/Button.stories.svelte | 20 +- js/button/static/StaticButton.svelte | 7 +- js/chatbot/package.json | 8 +- js/chatbot/static/ChatBot.svelte | 89 +- js/chatbot/static/MarkdownCode.svelte | 54 - js/chatbot/static/StaticChatbot.svelte | 19 +- js/chatbot/utils.ts | 189 --- .../interactive/InteractiveCheckbox.svelte | 12 +- js/checkbox/static/StaticCheckbox.svelte | 12 +- .../InteractiveCheckboxgroup.svelte | 12 +- .../static/StaticCheckboxgroup.svelte | 12 +- js/code/interactive/InteractiveCode.svelte | 16 +- js/code/package.json | 1 + js/code/static/StaticCode.svelte | 16 +- .../interactive/InteractiveColorpicker.svelte | 18 +- js/colorpicker/package.json | 3 +- .../static/StaticColorpicker.svelte | 19 +- .../interactive/InteractiveDataframe.svelte | 16 +- js/dataframe/package.json | 1 + js/dataframe/shared/EditableCell.svelte | 39 +- js/dataframe/shared/Table.svelte | 11 +- js/dataframe/static/StaticDataframe.svelte | 16 +- .../interactive/InteractiveDropdown.svelte | 18 +- js/dropdown/shared/Dropdown.svelte | 8 +- js/dropdown/static/StaticDropdown.svelte | 18 +- js/file/interactive/InteractiveFile.svelte | 29 +- js/file/shared/FilePreview.svelte | 4 +- js/file/static/StaticFile.svelte | 33 +- js/gallery/static/Gallery.svelte | 8 +- js/gallery/static/StaticGallery.svelte | 12 +- .../HighlightedText.stories.svelte | 8 + .../static/StaticHighlightedtext.svelte | 18 +- js/html/package.json | 3 +- js/html/static/HTML.svelte | 1 - js/html/static/StaticHtml.svelte | 11 +- js/image/Image.test.ts | 18 +- js/image/interactive/InteractiveImage.svelte | 32 +- js/image/interactive/Webcam.svelte | 6 +- js/image/static/StaticImage.svelte | 19 +- js/json/package.json | 3 +- js/json/static/StaticJson.svelte | 9 +- js/label/Label.component.spec.ts | 56 +- js/label/static/StaticLabel.svelte | 17 +- js/markdown/package.json | 6 +- js/markdown/static/Markdown.svelte | 35 +- js/markdown/static/MarkdownCode.svelte | 105 ++ js/markdown/static/StaticMarkdown.svelte | 11 +- js/markdown/static/index.ts | 1 + js/markdown/static/prism-dark.css | 68 ++ js/markdown/static/prism.css | 210 ++++ js/markdown/static/utils.ts | 193 +++ .../interactive/InteractiveModel3d.svelte | 9 +- js/model3D/interactive/Model3DUpload.svelte | 17 +- js/model3D/package.json | 1 + js/model3D/static/Model3D.svelte | 24 +- .../interactive/InteractiveNumber.svelte | 18 +- js/number/package.json | 3 +- js/number/static/StaticNumber.svelte | 18 +- js/plot/static/StaticPlot.svelte | 13 +- js/radio/interactive/InteractiveRadio.svelte | 12 +- js/radio/static/Radio.svelte | 12 +- js/slider/Slider.component.spec.ts | 34 +- .../interactive/InteractiveSlider.svelte | 12 +- js/slider/package.json | 3 +- js/slider/static/StaticSlider.svelte | 12 +- js/tabitem/static/StaticTabItem.svelte | 12 +- js/tabs/static/StaticTabs.svelte | 14 +- js/textbox/Textbox.test.ts | 14 +- .../interactive/InteractiveTextbox.svelte | 22 +- js/textbox/interactive/index.ts | 1 + js/textbox/static/StaticTextbox.svelte | 21 +- js/theme/src/typography.css | 16 +- .../interactive/InteractiveTimeseries.svelte | 17 +- js/tootils/src/render.ts | 65 +- js/upload/src/index.ts | 6 +- js/upload/src/utils.ts | 20 +- js/uploadbutton/UploadButton.test.ts | 19 +- .../InteractiveUploadButton.svelte | 19 +- js/uploadbutton/package.json | 3 +- .../static/StaticUploadButton.svelte | 19 +- js/utils/src/index.ts | 1 + js/utils/src/types.ts | 1 + js/utils/src/utils.ts | 68 ++ js/video/Video.test.ts | 9 +- js/video/interactive/InteractiveVideo.svelte | 35 +- js/video/static/StaticVideo.svelte | 32 +- js/video/static/VideoPreview.svelte | 3 +- package.json | 6 +- pnpm-lock.yaml | 126 +- test/test_files/xray_config.json | 923 +++++++------- test/test_files/xray_config_diff_ids.json | 923 +++++++------- test/test_files/xray_config_wrong.json | 1065 ++++++++--------- 117 files changed, 3216 insertions(+), 2461 deletions(-) create mode 100644 .changeset/chilly-chefs-hug.md create mode 100644 js/app/src/MountComponents.svelte create mode 100644 js/app/src/gradio_helper.ts delete mode 100644 js/chatbot/static/MarkdownCode.svelte create mode 100644 js/markdown/static/MarkdownCode.svelte create mode 100644 js/markdown/static/prism-dark.css create mode 100644 js/markdown/static/prism.css create mode 100644 js/markdown/static/utils.ts create mode 100644 js/utils/src/types.ts diff --git a/.changeset/chilly-chefs-hug.md b/.changeset/chilly-chefs-hug.md new file mode 100644 index 000000000000..4117d910bf15 --- /dev/null +++ b/.changeset/chilly-chefs-hug.md @@ -0,0 +1,56 @@ +--- +"@gradio/annotatedimage": patch +"@gradio/app": patch +"@gradio/atoms": patch +"@gradio/audio": patch +"@gradio/button": patch +"@gradio/chatbot": patch +"@gradio/checkbox": patch +"@gradio/checkboxgroup": patch +"@gradio/code": patch +"@gradio/colorpicker": patch +"@gradio/dataframe": patch +"@gradio/dropdown": patch +"@gradio/file": patch +"@gradio/gallery": patch +"@gradio/highlightedtext": patch +"@gradio/html": patch +"@gradio/image": patch +"@gradio/json": patch +"@gradio/label": patch +"@gradio/markdown": patch +"@gradio/model3d": patch +"@gradio/number": patch +"@gradio/plot": patch +"@gradio/radio": patch +"@gradio/slider": patch +"@gradio/tabitem": patch +"@gradio/tabs": patch +"@gradio/textbox": patch +"@gradio/theme": patch +"@gradio/timeseries": patch +"@gradio/tootils": patch +"@gradio/upload": patch +"@gradio/uploadbutton": patch +"@gradio/utils": patch +"@gradio/video": patch +"gradio": patch +"website": patch +--- + +highlight: + +#### Improve startup performance and markdown support + +##### Improved markdown support + +We now have better support for markdown in `gr.Markdown` and `gr.Dataframe`. Including syntax highlighting and Github Flavoured Markdown. We also have more consistent markdown behaviour and styling. + +##### Various performance improvements + +These improvements will be particularly beneficial to large applications. + +- Rather than attaching events manually, they are now delegated, leading to a significant performance improvement and addressing a performance regression introduced in a recent version of Gradio. App startup for large applications is now around twice as fast. +- Optimised the mounting of individual components, leading to a modest performance improvement during startup (~30%). +- Corrected an issue that was causing markdown to re-render infinitely. +- Ensured that the `gr.3DModel` does re-render prematurely. diff --git a/demo/event_trigger/run.ipynb b/demo/event_trigger/run.ipynb index 2a3131640f27..cda9ee87d8dc 100644 --- a/demo/event_trigger/run.ipynb +++ b/demo/event_trigger/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: event_trigger"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('img')\n", "!wget -q -O img/a.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/a.jpg\n", "!wget -q -O img/b.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/b.jpg\n", "os.mkdir('mp4')\n", "!wget -q -O mp4/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/a.mp4\n", "!wget -q -O mp4/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/b.mp4"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["# %%\n", "import gradio as gr\n", "\n", "\n", "TEST_VIDEO_A = \"mp4/a.mp4\"\n", "TEST_VIDEO_B = \"mp4/b.mp4\"\n", "\n", "TEST_IMAGE_A = \"img/a.jpg\"\n", "TEST_IMAGE_B = \"img/b.jpg\"\n", "\n", "\n", "def alert_change(component, value):\n", " print(f\"Detected {component} change, {type(value)}\")\n", "\n", " if type(value) == list or type(value) == str:\n", " print(value)\n", "\n", "\n", "def change_interactive(state):\n", " return gr.update(interactive=not state), not state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(label=\"Text change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " textbox1 = gr.Textbox()\n", " textbox2 = gr.Textbox(interactive=True)\n", "\n", " with gr.Column():\n", " btn = gr.Button()\n", "\n", " def btn_click(state):\n", " return state\n", "\n", " def text_change(value):\n", " print(\"text_change\", value)\n", "\n", " btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)\n", " textbox2.change(fn=alert_change, inputs=[gr.State(\"Text\"), textbox2])\n", "\n", " with gr.Tab(label=\"Video change, play, pause\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio1 = gr.Radio(\n", " choices=[TEST_VIDEO_A, TEST_VIDEO_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " video_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)\n", " video1_interactive = gr.State(value=False)\n", "\n", " def change_video(index):\n", " if index == 0:\n", " return TEST_VIDEO_A\n", " elif index == 1:\n", " return TEST_VIDEO_B\n", "\n", " def video_play():\n", " print(\"video_play\")\n", "\n", " def video_pause():\n", " print(\"video_pause\")\n", "\n", " def video_stop():\n", " print(\"video_stop\")\n", "\n", " video1.play(fn=video_play)\n", " video1.pause(fn=video_pause)\n", " video1.stop(fn=video_stop)\n", "\n", " radio1.change(fn=change_video, inputs=radio1, outputs=video1)\n", " video1.change(fn=alert_change, inputs=[gr.State(\"Video\"), video1])\n", "\n", " video_btn.click(\n", " fn=change_interactive,\n", " inputs=video1_interactive,\n", " outputs=[video1, video1_interactive],\n", " )\n", "\n", " with gr.Tab(label=\"Image change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio2 = gr.Radio(\n", " choices=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " with gr.Column():\n", " image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)\n", "\n", " def change_image(index):\n", " if index == 0:\n", " return TEST_IMAGE_A\n", " elif index == 1:\n", " return TEST_IMAGE_B\n", "\n", " radio2.change(fn=change_image, inputs=radio2, outputs=image1)\n", " image1.change(fn=alert_change, inputs=[gr.State(\"Image\"), image1])\n", "\n", " with gr.Tab(label=\"File\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio3 = gr.Radio(\n", " choices=[\"A\", \"B\", \"AB\"],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " file_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " file1 = gr.File(\n", " value=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=False,\n", " file_count=\"multiple\",\n", " )\n", " file1_interactive = gr.State(value=False)\n", "\n", " def change_file(index):\n", " if index == 0:\n", " return [TEST_IMAGE_A]\n", " elif index == 1:\n", " return [TEST_IMAGE_A]\n", " elif index == 2:\n", " return [TEST_IMAGE_A, TEST_IMAGE_B]\n", "\n", " radio3.change(fn=change_file, inputs=radio3, outputs=file1)\n", " file1.change(fn=alert_change, inputs=[gr.State(\"File\"), file1])\n", "\n", " file_btn.click(\n", " fn=change_interactive,\n", " inputs=file1_interactive,\n", " outputs=[file1, file1_interactive],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: event_trigger"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('img')\n", "!wget -q -O img/a.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/a.jpg\n", "!wget -q -O img/b.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/b.jpg\n", "os.mkdir('mp4')\n", "!wget -q -O mp4/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/a.mp4\n", "!wget -q -O mp4/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/b.mp4"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["# %%\n", "import gradio as gr\n", "\n", "\n", "TEST_VIDEO_A = \"mp4/a.mp4\"\n", "TEST_VIDEO_B = \"mp4/b.mp4\"\n", "\n", "TEST_IMAGE_A = \"img/a.jpg\"\n", "TEST_IMAGE_B = \"img/b.jpg\"\n", "\n", "\n", "def alert_change(component, value):\n", " print(f\"Detected {component} change, {type(value)}\")\n", "\n", " if type(value) == list or type(value) == str:\n", " print(value)\n", "\n", "\n", "def change_interactive(state):\n", " return gr.update(interactive=not state), not state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(label=\"Text change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " textbox1 = gr.Textbox()\n", " textbox2 = gr.Textbox(interactive=True)\n", "\n", " with gr.Column():\n", " btn = gr.Button()\n", "\n", " def btn_click(state):\n", " return state\n", "\n", " def text_change(value):\n", " print(\"text_change\", value)\n", "\n", " btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)\n", " textbox2.change(fn=alert_change, inputs=[gr.State(\"Text\"), textbox2])\n", "\n", " with gr.Tab(label=\"Video change, play, pause\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio1 = gr.Radio(\n", " choices=[TEST_VIDEO_A, TEST_VIDEO_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " video_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)\n", " video1_interactive = gr.State(value=False)\n", "\n", " def change_video(index):\n", " if index == 0:\n", " return TEST_VIDEO_A\n", " elif index == 1:\n", " return TEST_VIDEO_B\n", "\n", " def video_play():\n", " print(\"video_play\")\n", "\n", " def video_pause():\n", " print(\"video_pause\")\n", "\n", " def video_stop():\n", " print(\"video_stop\")\n", "\n", " def video_end():\n", " print(\"video_end\")\n", "\n", " video1.play(fn=video_play)\n", " video1.pause(fn=video_pause)\n", " video1.stop(fn=video_stop)\n", " video1.end(fn=video_end)\n", "\n", " radio1.change(fn=change_video, inputs=radio1, outputs=video1)\n", " video1.change(fn=alert_change, inputs=[gr.State(\"Video\"), video1])\n", "\n", " video_btn.click(\n", " fn=change_interactive,\n", " inputs=video1_interactive,\n", " outputs=[video1, video1_interactive],\n", " )\n", "\n", " with gr.Tab(label=\"Image change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio2 = gr.Radio(\n", " choices=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " with gr.Column():\n", " image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)\n", "\n", " def change_image(index):\n", " if index == 0:\n", " return TEST_IMAGE_A\n", " elif index == 1:\n", " return TEST_IMAGE_B\n", "\n", " radio2.change(fn=change_image, inputs=radio2, outputs=image1)\n", " image1.change(fn=alert_change, inputs=[gr.State(\"Image\"), image1])\n", "\n", " with gr.Tab(label=\"File\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio3 = gr.Radio(\n", " choices=[\"A\", \"B\", \"AB\"],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " file_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " file1 = gr.File(\n", " value=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=False,\n", " file_count=\"multiple\",\n", " )\n", " file1_interactive = gr.State(value=False)\n", "\n", " def change_file(index):\n", " if index == 0:\n", " return [TEST_IMAGE_A]\n", " elif index == 1:\n", " return [TEST_IMAGE_A]\n", " elif index == 2:\n", " return [TEST_IMAGE_A, TEST_IMAGE_B]\n", "\n", " radio3.change(fn=change_file, inputs=radio3, outputs=file1)\n", " file1.change(fn=alert_change, inputs=[gr.State(\"File\"), file1])\n", "\n", " file_btn.click(\n", " fn=change_interactive,\n", " inputs=file1_interactive,\n", " outputs=[file1, file1_interactive],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/event_trigger/run.py b/demo/event_trigger/run.py index 4b7d16707e92..bc25dc47199c 100644 --- a/demo/event_trigger/run.py +++ b/demo/event_trigger/run.py @@ -69,9 +69,13 @@ def video_pause(): def video_stop(): print("video_stop") + def video_end(): + print("video_end") + video1.play(fn=video_play) video1.pause(fn=video_pause) video1.stop(fn=video_stop) + video1.end(fn=video_end) radio1.change(fn=change_video, inputs=radio1, outputs=video1) video1.change(fn=alert_change, inputs=[gr.State("Video"), video1]) diff --git a/demo/latex/run.ipynb b/demo/latex/run.ipynb index 009025aa894b..4d0585bdf0a9 100644 --- a/demo/latex/run.ipynb +++ b/demo/latex/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: latex"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " r\"\"\"\n", " # Hello World! $\\frac{\\sqrt{x + y}}{4}$ is today's lesson\n", "\n", " ## the $\\sqrt{x + y}$ is first\n", "\n", " Start with $\\frac{\\frac{x+1}{x+2}}{x+3}$ then we get $ 2+x $ and $3$.\n", " \n", " There are three formulas to know:\n", " \n", " the first is $\\gamma^2 + \\theta^2 = \\omega^2$\n", " \n", " $\\sqrt{x^2+1}\n", " $ is next\n", " \n", " Integral $\\int_{a}^{b} x^2 \\,dx$ is last\n", "\n", " Start typing below to see the output.\n", "\n", " I spent $5 at the grocery store. Then I bought a $2.50 ice cream cone.\n", " \"\"\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: latex"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " r\"\"\"\n", " # Hello World! $\\frac{\\sqrt{x + y}}{4}$ is today's lesson\n", "\n", " ## the $\\sqrt{x + y}$ is first\n", "\n", " Start with $\\frac{\\frac{x+1}{x+2}}{x+3}$ then we get $ 2+x $ and $3$.\n", " \n", " There are three formulas to know:\n", " \n", " the first is $\\gamma^2 + \\theta^2 = \\omega^2$\n", " \n", " $\\sqrt{x^2+1}$ is next\n", " \n", " Integral $\\int_{a}^{b} x^2 \\,dx$ is last\n", "\n", " Start typing below to see the output.\n", "\n", " I spent $5 at the grocery store. Then I bought a $2.50 ice cream cone.\n", " \"\"\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/latex/run.py b/demo/latex/run.py index 621e7f78ca77..eb49ecc596b5 100644 --- a/demo/latex/run.py +++ b/demo/latex/run.py @@ -13,8 +13,7 @@ the first is $\gamma^2 + \theta^2 = \omega^2$ - $\sqrt{x^2+1} - $ is next + $\sqrt{x^2+1}$ is next Integral $\int_{a}^{b} x^2 \,dx$ is last diff --git a/demo/markdown_example/run.ipynb b/demo/markdown_example/run.ipynb index d9743985da85..c00e0efb5329 100644 --- a/demo/markdown_example/run.ipynb +++ b/demo/markdown_example/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: markdown_example"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "css = (\n", " \"footer {display: none !important;} .gradio-container {min-height: 0px !important;}\"\n", ")\n", "\n", "# sample md stolen from https://dillinger.io/\n", "\n", "md = \"\"\"# Dillinger\n", "## _The Last Markdown Editor, Ever_\n", "\n", "[![Build Status](https://travis-ci.org/joemccann/dillinger.svg?branch=master)](https://travis-ci.org/joemccann/dillinger)\n", "\n", "Dillinger is a cloud-enabled, mobile-ready, offline-storage compatible,\n", "AngularJS-powered HTML5 Markdown editor.\n", "\n", "- Type some Markdown on the left\n", "- See HTML in the right\n", "- \u2728Magic \u2728\n", "\n", "## Features\n", "\n", "- Import a HTML file and watch it magically convert to Markdown\n", "- Drag and drop images (requires your Dropbox account be linked)\n", "- Import and save files from GitHub, Dropbox, Google Drive and One Drive\n", "- Drag and drop markdown and HTML files into Dillinger\n", "- Export documents as Markdown, HTML and PDF\n", "\n", "Markdown is a lightweight markup language based on the formatting conventions\n", "that people naturally use in email.\n", "As [John Gruber] writes on the [Markdown site][df1]\n", "\n", "> The overriding design goal for Markdown's\n", "> formatting syntax is to make it as readable\n", "> as possible. The idea is that a\n", "> Markdown-formatted document should be\n", "> publishable as-is, as plain text, without\n", "> looking like it's been marked up with tags\n", "> or formatting instructions.\n", "\n", "This text you see here is *actually- written in Markdown! To get a feel\n", "for Markdown's syntax, type some text into the left window and\n", "watch the results in the right.\n", "\n", "## Tech\n", "\n", "Dillinger uses a number of open source projects to work properly:\n", "\n", "- [AngularJS] - HTML enhanced for web apps!\n", "- [Ace Editor] - awesome web-based text editor\n", "- [markdown-it] - Markdown parser done right. Fast and easy to extend.\n", "- [Twitter Bootstrap] - great UI boilerplate for modern web apps\n", "- [node.js] - evented I/O for the backend\n", "- [Express] - fast node.js network app framework [@tjholowaychuk]\n", "- [Gulp] - the streaming build system\n", "- [Breakdance](https://breakdance.github.io/breakdance/) - HTML\n", "to Markdown converter\n", "- [jQuery] - duh\n", "\n", "And of course Dillinger itself is open source with a [public repository][dill]\n", " on GitHub.\n", "\n", "## Installation\n", "\n", "Dillinger requires [Node.js](https://nodejs.org/) v10+ to run.\n", "\n", "Install the dependencies and devDependencies and start the server.\n", "\n", "```sh\n", "cd dillinger\n", "npm i\n", "node app\n", "```\n", "\n", "For production environments...\n", "\n", "```sh\n", "npm install --production\n", "NODE_ENV=production node app\n", "```\n", "\n", "## Plugins\n", "\n", "Dillinger is currently extended with the following plugins.\n", "Instructions on how to use them in your own application are linked below.\n", "\n", "| Plugin | README |\n", "| ------ | ------ |\n", "| Dropbox | [plugins/dropbox/README.md][PlDb] |\n", "| GitHub | [plugins/github/README.md][PlGh] |\n", "| Google Drive | [plugins/googledrive/README.md][PlGd] |\n", "| OneDrive | [plugins/onedrive/README.md][PlOd] |\n", "| Medium | [plugins/medium/README.md][PlMe] |\n", "| Google Analytics | [plugins/googleanalytics/README.md][PlGa] |\n", "\n", "## Development\n", "\n", "Want to contribute? Great!\n", "\n", "Dillinger uses Gulp + Webpack for fast developing.\n", "Make a change in your file and instantaneously see your updates!\n", "\n", "Open your favorite Terminal and run these commands.\n", "\n", "First Tab:\n", "\n", "```sh\n", "node app\n", "```\n", "\n", "Second Tab:\n", "\n", "```sh\n", "gulp watch\n", "```\n", "\n", "(optional) Third:\n", "\n", "```sh\n", "karma test\n", "```\n", "\n", "#### Building for source\n", "\n", "For production release:\n", "\n", "```sh\n", "gulp build --prod\n", "```\n", "\n", "Generating pre-built zip archives for distribution:\n", "\n", "```sh\n", "gulp build dist --prod\n", "```\n", "\n", "## Docker\n", "\n", "Dillinger is very easy to install and deploy in a Docker container.\n", "\n", "By default, the Docker will expose port 8080, so change this within the\n", "Dockerfile if necessary. When ready, simply use the Dockerfile to\n", "build the image.\n", "\n", "```sh\n", "cd dillinger\n", "docker build -t /dillinger:${package.json.version} .\n", "```\n", "\n", "This will create the dillinger image and pull in the necessary dependencies.\n", "Be sure to swap out `${package.json.version}` with the actual\n", "version of Dillinger.\n", "\n", "Once done, run the Docker image and map the port to whatever you wish on\n", "your host. In this example, we simply map port 8000 of the host to\n", "port 8080 of the Docker (or whatever port was exposed in the Dockerfile):\n", "\n", "```sh\n", "docker run -d -p 8000:8080 --restart=always --cap-add=SYS_ADMIN --name=dillinger /dillinger:${package.json.version}\n", "```\n", "\n", "> Note: `--capt-add=SYS-ADMIN` is required for PDF rendering.\n", "\n", "Verify the deployment by navigating to your server address in\n", "your preferred browser.\n", "\n", "```sh\n", "127.0.0.1:8000\n", "```\n", "\n", "## License\n", "\n", "MIT\n", "\n", "**Free Software, Hell Yeah!**\n", "\n", "[//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job. There is no need to format nicely because it shouldn't be seen. Thanks SO - http://stackoverflow.com/questions/4823468/store-comments-in-markdown-syntax)\n", "\n", " [dill]: \n", " [git-repo-url]: \n", " [john gruber]: \n", " [df1]: \n", " [markdown-it]: \n", " [Ace Editor]: \n", " [node.js]: \n", " [Twitter Bootstrap]: \n", " [jQuery]: \n", " [@tjholowaychuk]: \n", " [express]: \n", " [AngularJS]: \n", " [Gulp]: \n", "\n", " [PlDb]: \n", " [PlGh]: \n", " [PlGd]: \n", " [PlOd]: \n", " [PlMe]: \n", " [PlGa]: \n", "\n", "\"\"\"\n", "with gr.Blocks(css=css) as demo:\n", " gr.Markdown(value=md)\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: markdown_example"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "css = (\n", " \"footer {display: none !important;} .gradio-container {min-height: 0px !important;}\"\n", ")\n", "\n", "# sample md stolen from https://dillinger.io/\n", "\n", "md = \"\"\"# Dillinger\n", "## _The Last Markdown Editor, Ever_\n", "\n", "[![Build Status](https://travis-ci.org/joemccann/dillinger.svg?branch=master)](https://travis-ci.org/joemccann/dillinger)\n", "\n", "Dillinger is a cloud-enabled, mobile-ready, offline-storage compatible,\n", "AngularJS-powered HTML5 Markdown editor.\n", "\n", "- Type some Markdown on the left\n", "- See HTML in the right\n", "- \u2728Magic \u2728\n", "\n", "## Features\n", "\n", "- Import a HTML file and watch it magically convert to Markdown\n", "- Drag and drop images (requires your Dropbox account be linked)\n", "- Import and save files from GitHub, Dropbox, Google Drive and One Drive\n", "- Drag and drop markdown and HTML files into Dillinger\n", "- Export documents as Markdown, HTML and PDF\n", "\n", "Markdown is a lightweight markup language based on the formatting conventions\n", "that people naturally use in email.\n", "As [John Gruber] writes on the [Markdown site][df1]\n", "\n", "> The overriding design goal for Markdown's\n", "> formatting syntax is to make it as readable\n", "> as possible. The idea is that a\n", "> Markdown-formatted document should be\n", "> publishable as-is, as plain text, without\n", "> looking like it's been marked up with tags\n", "> or formatting instructions.\n", "\n", "This text you see here is *actually- written in Markdown! To get a feel\n", "for Markdown's syntax, type some text into the left window and\n", "watch the results in the right.\n", "\n", "## Tech\n", "\n", "Dillinger uses a number of open source projects to work properly:\n", "\n", "- [AngularJS] - HTML enhanced for web apps!\n", "- [Ace Editor] - awesome web-based text editor\n", "- [markdown-it] - Markdown parser done right. Fast and easy to extend.\n", "- [Twitter Bootstrap] - great UI boilerplate for modern web apps\n", "- [node.js] - evented I/O for the backend\n", "- [Express] - fast node.js network app framework [@tjholowaychuk]\n", "- [Gulp] - the streaming build system\n", "- [Breakdance](https://breakdance.github.io/breakdance/) - HTML\n", "to Markdown converter\n", "- [jQuery] - duh\n", "\n", "And of course Dillinger itself is open source with a [public repository][dill]\n", " on GitHub.\n", "\n", "## Installation\n", "\n", "Dillinger requires [Node.js](https://nodejs.org/) v10+ to run.\n", "\n", "Install the dependencies and devDependencies and start the server.\n", "\n", "```sh\n", "cd dillinger\n", "npm i\n", "node app\n", "```\n", "\n", "For production environments...\n", "\n", "```sh\n", "npm install --production\n", "NODE_ENV=production node app\n", "```\n", "\n", "## Plugins\n", "\n", "Dillinger is currently extended with the following plugins.\n", "Instructions on how to use them in your own application are linked below.\n", "\n", "| Plugin | README |\n", "| ------ | ------ |\n", "| Dropbox | [plugins/dropbox/README.md][PlDb] |\n", "| GitHub | [plugins/github/README.md][PlGh] |\n", "| Google Drive | [plugins/googledrive/README.md][PlGd] |\n", "| OneDrive | [plugins/onedrive/README.md][PlOd] |\n", "| Medium | [plugins/medium/README.md][PlMe] |\n", "| Google Analytics | [plugins/googleanalytics/README.md][PlGa] |\n", "\n", "## Development\n", "\n", "Want to contribute? Great!\n", "\n", "Dillinger uses Gulp + Webpack for fast developing.\n", "Make a change in your file and instantaneously see your updates!\n", "\n", "Open your favorite Terminal and run these commands.\n", "\n", "First Tab:\n", "\n", "```sh\n", "node app\n", "```\n", "\n", "Second Tab:\n", "\n", "```sh\n", "gulp watch\n", "```\n", "\n", "(optional) Third:\n", "\n", "```sh\n", "karma test\n", "```\n", "\n", "#### Building for source\n", "\n", "For production release:\n", "\n", "```sh\n", "gulp build --prod\n", "```\n", "\n", "Generating pre-built zip archives for distribution:\n", "\n", "```sh\n", "gulp build dist --prod\n", "```\n", "\n", "## Docker\n", "\n", "Dillinger is very easy to install and deploy in a Docker container.\n", "\n", "By default, the Docker will expose port 8080, so change this within the\n", "Dockerfile if necessary. When ready, simply use the Dockerfile to\n", "build the image.\n", "\n", "```sh\n", "cd dillinger\n", "docker build -t /dillinger:${package.json.version} .\n", "```\n", "\n", "This will create the dillinger image and pull in the necessary dependencies.\n", "Be sure to swap out `${package.json.version}` with the actual\n", "version of Dillinger.\n", "\n", "Once done, run the Docker image and map the port to whatever you wish on\n", "your host. In this example, we simply map port 8000 of the host to\n", "port 8080 of the Docker (or whatever port was exposed in the Dockerfile):\n", "\n", "```sh\n", "docker run -d -p 8000:8080 --restart=always --cap-add=SYS_ADMIN --name=dillinger /dillinger:${package.json.version}\n", "```\n", "\n", "> Note: `--capt-add=SYS-ADMIN` is required for PDF rendering.\n", "\n", "Verify the deployment by navigating to your server address in\n", "your preferred browser.\n", "\n", "```sh\n", "127.0.0.1:8000\n", "```\n", "\n", "```python\n", "import gradio as gr\n", "\n", "gr.Blocks() as demo:\n", " gr.Markdown(value=md)\n", "\n", "demo.launch()\n", "```\n", "\n", "```js\n", "function fancyAlert(arg) {\n", " if(arg) {\n", " $.facebox({div:'#foo'})\n", " }\n", "}\n", "```\n", "\n", "## License\n", "\n", "MIT\n", "\n", "**Free Software, Hell Yeah!**\n", "\n", "[//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job. There is no need to format nicely because it shouldn't be seen. Thanks SO - http://stackoverflow.com/questions/4823468/store-comments-in-markdown-syntax)\n", "\n", " [dill]: \n", " [git-repo-url]: \n", " [john gruber]: \n", " [df1]: \n", " [markdown-it]: \n", " [Ace Editor]: \n", " [node.js]: \n", " [Twitter Bootstrap]: \n", " [jQuery]: \n", " [@tjholowaychuk]: \n", " [express]: \n", " [AngularJS]: \n", " [Gulp]: \n", "\n", " [PlDb]: \n", " [PlGh]: \n", " [PlGd]: \n", " [PlOd]: \n", " [PlMe]: \n", " [PlGa]: \n", "\n", "\"\"\"\n", "with gr.Blocks(css=css) as demo:\n", " gr.Markdown(value=md)\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/markdown_example/run.py b/demo/markdown_example/run.py index 5d03f6861ce8..fae251f562ae 100644 --- a/demo/markdown_example/run.py +++ b/demo/markdown_example/run.py @@ -168,6 +168,23 @@ 127.0.0.1:8000 ``` +```python +import gradio as gr + +gr.Blocks() as demo: + gr.Markdown(value=md) + +demo.launch() +``` + +```js +function fancyAlert(arg) { + if(arg) { + $.facebox({div:'#foo'}) + } +} +``` + ## License MIT diff --git a/js/_website/src/lib/assets/prism.css b/js/_website/src/lib/assets/prism.css index 8a1b9c2aa795..256c26f16e48 100644 --- a/js/_website/src/lib/assets/prism.css +++ b/js/_website/src/lib/assets/prism.css @@ -9,7 +9,6 @@ https://prismjs.com/download.html#themes=prism&languages=python */ code[class*="language-"], pre[class*="language-"] { word-wrap: normal; - background: none; color: black; font-size: 1em; line-height: 1.5; diff --git a/js/annotatedimage/static/AnnotatedImage.svelte b/js/annotatedimage/static/AnnotatedImage.svelte index df65dcc07d35..59b264ef61e6 100644 --- a/js/annotatedimage/static/AnnotatedImage.svelte +++ b/js/annotatedimage/static/AnnotatedImage.svelte @@ -1,11 +1,11 @@ handle_mouseover(label)} on:mouseout={() => handle_mouseout()} on:blur={() => handle_mouseout()} - on:click={() => dispatch("select", { index: i, value: label })} + on:click={() => handle_click(i)} > {label} diff --git a/js/app/package.json b/js/app/package.json index 6067cf61416e..c451e0c6c2f9 100644 --- a/js/app/package.json +++ b/js/app/package.json @@ -67,7 +67,6 @@ "@gradio/utils": "workspace:^", "@gradio/video": "workspace:^", "@gradio/wasm": "workspace:^", - "@playwright/test": "^1.35.1", "d3-dsv": "^3.0.1", "mime-types": "^2.1.34", "postcss": "^8.4.21", diff --git a/js/app/src/Blocks.svelte b/js/app/src/Blocks.svelte index 81980d05ff1e..2014b9598bac 100644 --- a/js/app/src/Blocks.svelte +++ b/js/app/src/Blocks.svelte @@ -1,5 +1,5 @@ @@ -635,11 +615,8 @@
{#if ready} - handle_destroy(detail)} + {version} /> {/if}
diff --git a/js/app/src/Index.svelte b/js/app/src/Index.svelte index 059f2fc7b5b6..7df4b696fbd0 100644 --- a/js/app/src/Index.svelte +++ b/js/app/src/Index.svelte @@ -5,7 +5,7 @@ import type { ComponentMeta, Dependency, - LayoutNode, + LayoutNode } from "./components/types"; declare let BUILD_MODE: string; @@ -188,7 +188,7 @@ message: "", load_status: "pending", status: "sleeping", - detail: "SLEEPING", + detail: "SLEEPING" }; let app: Awaited>; @@ -208,7 +208,7 @@ app = await client(api_url, { status_callback: handle_status, - normalise_files: false, + normalise_files: false }); config = app.config; window.__gradio_space__ = config.space_id; @@ -217,7 +217,7 @@ message: "", load_status: "complete", status: "running", - detail: "RUNNING", + detail: "RUNNING" }; await mount_custom_css(wrapper, config.css); @@ -269,7 +269,7 @@ CONFIG_ERROR: $_("errors.config_error"), BUILD_ERROR: $_("errors.build_error"), RUNTIME_ERROR: $_("errors.runtime_error"), - PAUSED: $_("errors.space_paused"), + PAUSED: $_("errors.space_paused") } as const, title(error: error_types): string { return encodeURIComponent($_("errors.space_not_working")); @@ -280,7 +280,7 @@ this.readable_error[error] || "an error" }.\n\nIt would be great if you could take a look at this because this space is being embedded on ${site}.\n\nThanks!` ); - }, + } }; onMount(async () => { @@ -292,7 +292,7 @@ new CustomEvent("render", { bubbles: true, cancelable: false, - composed: true, + composed: true }) ); } @@ -359,6 +359,7 @@ bind:render_complete show_footer={!is_embed} {app_mode} + {version} /> {/if} diff --git a/js/app/src/Login.svelte b/js/app/src/Login.svelte index e443bbf33e78..1ef8951e0c68 100644 --- a/js/app/src/Login.svelte +++ b/js/app/src/Login.svelte @@ -1,6 +1,6 @@ + + diff --git a/js/app/src/Render.svelte b/js/app/src/Render.svelte index c06e6233a338..e1bb80bd8f7f 100644 --- a/js/app/src/Render.svelte +++ b/js/app/src/Render.svelte @@ -1,4 +1,5 @@ diff --git a/js/audio/interactive/Audio.svelte b/js/audio/interactive/Audio.svelte index 7e02ab770b0c..842f820372e1 100644 --- a/js/audio/interactive/Audio.svelte +++ b/js/audio/interactive/Audio.svelte @@ -53,7 +53,7 @@ function get_modules(): void { module_promises = [ import("extendable-media-recorder"), - import("extendable-media-recorder-wav-encoder"), + import("extendable-media-recorder-wav-encoder") ]; } @@ -93,7 +93,7 @@ let _audio_blob = new Blob(blobs, { type: "audio/wav" }); value = { data: await blob_to_data_url(_audio_blob), - name: "audio.wav", + name: "audio.wav" }; dispatch(event, value); }; @@ -202,7 +202,7 @@ } function handle_change({ - detail: { values }, + detail: { values } }: { detail: { values: [number, number] }; }): void { @@ -212,14 +212,14 @@ data: value.data, name, crop_min: values[0], - crop_max: values[1], + crop_max: values[1] }); dispatch("edit"); } function handle_load({ - detail, + detail }: { detail: { data: string; diff --git a/js/audio/interactive/InteractiveAudio.svelte b/js/audio/interactive/InteractiveAudio.svelte index 89348623ca96..cf53e203829c 100644 --- a/js/audio/interactive/InteractiveAudio.svelte +++ b/js/audio/interactive/InteractiveAudio.svelte @@ -1,7 +1,7 @@ @@ -31,7 +36,7 @@ {root} {root_url} disabled={mode === "static"} - on:click + on:click={() => gradio.dispatch("click")} > {$_(value)} diff --git a/js/chatbot/package.json b/js/chatbot/package.json index 492b6eeaded7..9fc72f61b52a 100644 --- a/js/chatbot/package.json +++ b/js/chatbot/package.json @@ -10,18 +10,14 @@ "dependencies": { "@gradio/atoms": "workspace:^", "@gradio/icons": "workspace:^", + "@gradio/markdown": "workspace:^", "@gradio/statustracker": "workspace:^", "@gradio/theme": "workspace:^", "@gradio/upload": "workspace:^", "@gradio/utils": "workspace:^", "@types/dompurify": "^3.0.2", "@types/katex": "^0.16.0", - "@types/prismjs": "1.26.0", - "dompurify": "^3.0.3", - "katex": "^0.16.7", - "marked": "^7.0.0", - "marked-highlight": "^2.0.1", - "prismjs": "1.29.0" + "@types/prismjs": "1.26.0" }, "main_changeset": true, "exports": { diff --git a/js/chatbot/static/ChatBot.svelte b/js/chatbot/static/ChatBot.svelte index 6c303c78731e..1dda8e1cc1b1 100644 --- a/js/chatbot/static/ChatBot.svelte +++ b/js/chatbot/static/ChatBot.svelte @@ -1,22 +1,16 @@ - - - - diff --git a/js/chatbot/static/StaticChatbot.svelte b/js/chatbot/static/StaticChatbot.svelte index d2c30170e600..40d0cd284e86 100644 --- a/js/chatbot/static/StaticChatbot.svelte +++ b/js/chatbot/static/StaticChatbot.svelte @@ -1,8 +1,9 @@ @@ -28,8 +34,8 @@ {label} bind:value bind:value_is_output - on:change - on:input - on:select + on:change={() => gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:select={() => gradio.dispatch("select")} /> diff --git a/js/checkbox/static/StaticCheckbox.svelte b/js/checkbox/static/StaticCheckbox.svelte index 43924a8c4acd..6e64e3591fba 100644 --- a/js/checkbox/static/StaticCheckbox.svelte +++ b/js/checkbox/static/StaticCheckbox.svelte @@ -1,4 +1,5 @@ @@ -27,9 +33,9 @@ {label} bind:value bind:value_is_output - on:change - on:input - on:select + on:change={() => gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:select={() => gradio.dispatch("select")} disabled /> diff --git a/js/checkboxgroup/interactive/InteractiveCheckboxgroup.svelte b/js/checkboxgroup/interactive/InteractiveCheckboxgroup.svelte index 3f191963de07..5ec4af69db1e 100644 --- a/js/checkboxgroup/interactive/InteractiveCheckboxgroup.svelte +++ b/js/checkboxgroup/interactive/InteractiveCheckboxgroup.svelte @@ -1,4 +1,5 @@ @@ -39,8 +45,8 @@ {label} {info} {show_label} - on:select - on:change - on:input + on:select={(e) => gradio.dispatch("select", e.detail)} + on:change={() => gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} /> diff --git a/js/checkboxgroup/static/StaticCheckboxgroup.svelte b/js/checkboxgroup/static/StaticCheckboxgroup.svelte index bb6800eef5ec..09480116b11d 100644 --- a/js/checkboxgroup/static/StaticCheckboxgroup.svelte +++ b/js/checkboxgroup/static/StaticCheckboxgroup.svelte @@ -1,4 +1,5 @@ @@ -38,9 +44,9 @@ {label} {info} {show_label} - on:select - on:change - on:input + on:select={(e) => gradio.dispatch("select", e.detail)} + on:change={() => gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} disabled /> diff --git a/js/code/interactive/InteractiveCode.svelte b/js/code/interactive/InteractiveCode.svelte index d6ecf7677ed7..7d1660c074c5 100644 --- a/js/code/interactive/InteractiveCode.svelte +++ b/js/code/interactive/InteractiveCode.svelte @@ -1,5 +1,6 @@ @@ -32,10 +40,10 @@ {info} {show_label} disabled={!interactive} - on:change - on:input - on:submit - on:blur - on:focus + on:change={() => gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:submit={() => gradio.dispatch("submit")} + on:blur={() => gradio.dispatch("blur")} + on:focus={() => gradio.dispatch("focus")} /> diff --git a/js/colorpicker/package.json b/js/colorpicker/package.json index 7329e325a3dc..8ce10df2a811 100644 --- a/js/colorpicker/package.json +++ b/js/colorpicker/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@gradio/atoms": "workspace:^", - "@gradio/statustracker": "workspace:^" + "@gradio/statustracker": "workspace:^", + "@gradio/utils": "workspace:^" } } diff --git a/js/colorpicker/static/StaticColorpicker.svelte b/js/colorpicker/static/StaticColorpicker.svelte index 646ddf4ef641..6837f55ce015 100644 --- a/js/colorpicker/static/StaticColorpicker.svelte +++ b/js/colorpicker/static/StaticColorpicker.svelte @@ -1,10 +1,12 @@ @@ -31,10 +40,10 @@ {info} {show_label} disabled={!interactive} - on:change - on:input - on:submit - on:blur - on:focus + on:change={() => gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:submit={() => gradio.dispatch("submit")} + on:blur={() => gradio.dispatch("blur")} + on:focus={() => gradio.dispatch("focus")} /> diff --git a/js/dataframe/interactive/InteractiveDataframe.svelte b/js/dataframe/interactive/InteractiveDataframe.svelte index 351ed1dbc0d0..353fe6b20ad0 100644 --- a/js/dataframe/interactive/InteractiveDataframe.svelte +++ b/js/dataframe/interactive/InteractiveDataframe.svelte @@ -1,9 +1,10 @@ {#if edit} { value = currentTarget.value; @@ -57,9 +33,16 @@ }} /> {/if} - + + {#if datatype === "html"} {@html value} + {:else if datatype === "markdown"} + {:else} {value} {/if} diff --git a/js/dataframe/shared/Table.svelte b/js/dataframe/shared/Table.svelte index a0969fac3c28..0a6050ef9011 100644 --- a/js/dataframe/shared/Table.svelte +++ b/js/dataframe/shared/Table.svelte @@ -2,7 +2,7 @@ import { createEventDispatcher, tick } from "svelte"; import { dsvFormat } from "d3-dsv"; import { dequal } from "dequal/lite"; - + import { copy } from "@gradio/utils"; import { Upload } from "@gradio/upload"; import { BaseButton } from "@gradio/button/static"; import EditableCell from "./EditableCell.svelte"; @@ -534,13 +534,18 @@ on:touchstart={handle_click_outside} /> -
+
{#if label && label.length !== 0}

{label}

{/if} -
+
+ import { afterUpdate } from "svelte"; + import type { Gradio, SelectData } from "@gradio/utils"; import { Block } from "@gradio/atoms"; import Table from "../shared"; import { StatusTracker } from "@gradio/statustracker"; import type { LoadingStatus } from "@gradio/statustracker"; - import { createEventDispatcher, afterUpdate } from "svelte"; type Headers = string[]; type Data = (string | number)[][]; @@ -26,6 +27,11 @@ export let datatype: Datatype | Datatype[]; export let scale: number | null = null; export let min_width: number | undefined = undefined; + export let gradio: Gradio<{ + change: never; + select: SelectData; + input: never; + }>; export let latex_delimiters: { left: string; right: string; @@ -33,14 +39,12 @@ }[]; export let height: number | undefined = undefined; - const dispatch = createEventDispatcher(); - export let loading_status: LoadingStatus; function handle_change(): void { - dispatch("change", value); + gradio.dispatch("change"); if (!value_is_output) { - dispatch("input"); + gradio.dispatch("input"); } } afterUpdate(() => { @@ -74,7 +78,7 @@ on:change={({ detail }) => { value = detail; }} - on:select + on:select={(e) => gradio.dispatch("select", e.detail)} {wrap} {datatype} {latex_delimiters} diff --git a/js/dropdown/interactive/InteractiveDropdown.svelte b/js/dropdown/interactive/InteractiveDropdown.svelte index e3f80a01222b..de73864b2068 100644 --- a/js/dropdown/interactive/InteractiveDropdown.svelte +++ b/js/dropdown/interactive/InteractiveDropdown.svelte @@ -1,4 +1,5 @@ gradio.dispatch("select", e.detail)} + on:share={(e) => gradio.dispatch("share", e.detail)} + on:error={(e) => gradio.dispatch("error", e.detail)} {label} {value} {show_label} diff --git a/js/highlightedtext/HighlightedText.stories.svelte b/js/highlightedtext/HighlightedText.stories.svelte index c54a262ba13d..8ed382f5ac71 100644 --- a/js/highlightedtext/HighlightedText.stories.svelte +++ b/js/highlightedtext/HighlightedText.stories.svelte @@ -1,6 +1,7 @@ @@ -12,6 +13,13 @@ ["dogs", "-"], ["elephants", "+"] ]} + gradio={new Gradio( + 0, + document.body, + "light", + "1.1.1", + "http://localhost:7860" + )} {...args} /> diff --git a/js/highlightedtext/static/StaticHighlightedtext.svelte b/js/highlightedtext/static/StaticHighlightedtext.svelte index fbe99eaeea6c..e54824d5f333 100644 --- a/js/highlightedtext/static/StaticHighlightedtext.svelte +++ b/js/highlightedtext/static/StaticHighlightedtext.svelte @@ -1,5 +1,5 @@ @@ -57,7 +59,13 @@ {/if} {#if value} - + gradio.dispatch("select", detail)} + {selectable} + {value} + {show_legend} + {color_map} + /> {:else} diff --git a/js/html/package.json b/js/html/package.json index 260aae001503..f485aeaec2c1 100644 --- a/js/html/package.json +++ b/js/html/package.json @@ -10,7 +10,8 @@ "main_changeset": true, "dependencies": { "@gradio/atoms": "workspace:^", - "@gradio/statustracker": "workspace:^" + "@gradio/statustracker": "workspace:^", + "@gradio/utils": "workspace:^" }, "exports": { ".": "./static/index.ts", diff --git a/js/html/static/HTML.svelte b/js/html/static/HTML.svelte index ba9473a45364..81ef1a4ff199 100644 --- a/js/html/static/HTML.svelte +++ b/js/html/static/HTML.svelte @@ -1,6 +1,5 @@ @@ -26,7 +27,7 @@ {elem_id} {elem_classes} {visible} - on:change + on:change={() => gradio.dispatch("change")} />
diff --git a/js/image/Image.test.ts b/js/image/Image.test.ts index b9f94a466aa6..99b295630bb9 100644 --- a/js/image/Image.test.ts +++ b/js/image/Image.test.ts @@ -34,21 +34,25 @@ describe("Image", () => { afterEach(() => cleanup()); test("image change event trigger fires when value is changed and only fires once", async () => { - const { component } = await render(Image, { + const { component, listen } = await render(Image, { show_label: true, loading_status, - mode: "dynamic", value: "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png", - root: "foo", - root_url: null, streaming: false, pending: false, - source: "upload" + source: "upload", + label: "Test Label", + width: 224, + height: 224, + mirror_webcam: false, + shape: [224, 224], + brush_color: "#000000", + brush_radius: 5, + mask_opacity: 0.5 }); - const mock = spy(); - component.$on("change", mock); + const mock = listen("change"); component.value = "https://github.com/gradio-app/gradio/blob/main/test/test_files/cheetah1.jpg"; diff --git a/js/image/interactive/InteractiveImage.svelte b/js/image/interactive/InteractiveImage.svelte index 68312b9f93ff..9a9d6cd6b364 100644 --- a/js/image/interactive/InteractiveImage.svelte +++ b/js/image/interactive/InteractiveImage.svelte @@ -1,7 +1,7 @@ diff --git a/js/label/Label.component.spec.ts b/js/label/Label.component.spec.ts index 370a9ec2a691..9cb07e5aa39e 100644 --- a/js/label/Label.component.spec.ts +++ b/js/label/Label.component.spec.ts @@ -30,7 +30,10 @@ test("gr.Label default value and label rendered with confidences", async ({ }, label: "My Label", show_label: true, - loading_status: loading_status + loading_status: loading_status, + gradio: { + dispatch() {} + } } }); await expect(component).toContainText("My Label"); @@ -52,7 +55,10 @@ test("gr.Label hides label when show_label=false", async ({ mount, page }) => { }, label: "My Label", show_label: false, - loading_status: loading_status + loading_status: loading_status, + gradio: { + dispatch() {} + } } }); await expect(component.getByTestId("block-label")).toBeHidden(); @@ -68,7 +74,10 @@ test("gr.Label confidence bars not rendered without confidences", async ({ }, label: "My Label", show_label: true, - loading_status: loading_status + loading_status: loading_status, + gradio: { + dispatch() {} + } } }); await expect(component).toContainText("My Label"); @@ -79,7 +88,14 @@ test("gr.Label confidence bars trigger select event when clicked", async ({ mount, page }) => { - const select = spy(); + const events = { + select: [0, null] + }; + + function event(name: "select", value: any) { + events[name] = [events[name][0]! + 1, value]; + } + const component = await mount(Label, { props: { value: { @@ -91,20 +107,27 @@ test("gr.Label confidence bars trigger select event when clicked", async ({ }, label: "My Label", show_label: true, - loading_status: loading_status - }, - on: { - select: select + loading_status: loading_status, + gradio: { + dispatch: event + } } }); await expect(component).toContainText("My Label"); await component.getByTestId("Bad-confidence-set").click(); - expect(select.callCount).toEqual(1); - expect(select.calls[0][0]).toEqual({ index: 1, value: "Bad" }); + expect(events.select[0]).toEqual(1); + expect(events.select[1]).toEqual({ index: 1, value: "Bad" }); }); test("gr.Label triggers change event", async ({ mount, page }) => { - const change = spy(); + const events = { + change: 0 + }; + + function event(name: "change") { + events[name] += 1; + } + const component = await mount(Label, { props: { value: { @@ -116,12 +139,13 @@ test("gr.Label triggers change event", async ({ mount, page }) => { }, label: "My Label", show_label: true, - loading_status: loading_status - }, - on: { - change: change + loading_status: loading_status, + gradio: { + dispatch: event + } } }); + await component.update({ props: { value: { @@ -133,5 +157,5 @@ test("gr.Label triggers change event", async ({ mount, page }) => { } } }); - expect(change.callCount).toEqual(1); + expect(events.change).toEqual(2); }); diff --git a/js/label/static/StaticLabel.svelte b/js/label/static/StaticLabel.svelte index cfd693d5a607..6ba1ce60f5f6 100644 --- a/js/label/static/StaticLabel.svelte +++ b/js/label/static/StaticLabel.svelte @@ -1,5 +1,5 @@ {/if} {#if _label !== undefined && _label !== null} -
diff --git a/js/markdown/static/StaticMarkdown.svelte b/js/markdown/static/StaticMarkdown.svelte index 9a32cc3cc7bb..fb2090b05c9d 100644 --- a/js/markdown/static/StaticMarkdown.svelte +++ b/js/markdown/static/StaticMarkdown.svelte @@ -1,5 +1,5 @@ @@ -34,8 +35,8 @@ {elem_classes} {visible} {rtl} + on:change={() => gradio.dispatch("change")} {latex_delimiters} - on:change />
diff --git a/js/markdown/static/index.ts b/js/markdown/static/index.ts index e47be6135006..72f376e65ead 100644 --- a/js/markdown/static/index.ts +++ b/js/markdown/static/index.ts @@ -1 +1,2 @@ export { default } from "./StaticMarkdown.svelte"; +export { default as MarkdownCode } from "./MarkdownCode.svelte"; diff --git a/js/markdown/static/prism-dark.css b/js/markdown/static/prism-dark.css new file mode 100644 index 000000000000..892bd5932e14 --- /dev/null +++ b/js/markdown/static/prism-dark.css @@ -0,0 +1,68 @@ +.dark .md .token.comment, +.dark .md .token.prolog, +.dark .md .token.doctype, +.dark .md .token.cdata { + color: hsl(30, 20%, 50%); +} + +.dark .md .token.punctuation { + opacity: 0.7; +} + +.dark .md .token.namespace { + opacity: 0.7; +} + +.dark .md .token.property, +.dark .md .token.tag, +.dark .md .token.boolean, +.dark .md .token.number, +.dark .md .token.constant, +.dark .md .token.symbol { + color: hsl(350, 40%, 70%); +} + +.dark .md .token.selector, +.dark .md .token.attr-name, +.dark .md .token.string, +.dark .md .token.char, +.dark .md .token.builtin, +.dark .md .token.inserted { + color: hsl(75, 70%, 60%); +} + +.dark .md .token.operator, +.dark .md .token.entity, +.dark .md .token.url, +.dark .md .language-css .token.string, +.dark .md .style .token.string, +.dark .md .token.variable { + color: hsl(40, 90%, 60%); +} + +.dark .md .token.atrule, +.dark .md .token.attr-value, +.dark .md .token.keyword { + color: hsl(350, 40%, 70%); +} + +.dark .md .token.regex, +.dark .md .token.important { + color: #e90; +} + +.dark .md .token.important, +.dark .md .token.bold { + font-weight: bold; +} +.dark .md .token.italic { + font-style: italic; +} + +.dark .md .token.entity { + cursor: help; +} + +.dark .md .token.deleted { + color: red; +} diff --git a/js/markdown/static/prism.css b/js/markdown/static/prism.css new file mode 100644 index 000000000000..c6da6d2400dc --- /dev/null +++ b/js/markdown/static/prism.css @@ -0,0 +1,210 @@ +Tables */ table, +tr, +td, +th { + margin-top: var(--spacing-sm); + margin-bottom: var(--spacing-sm); + padding: var(--spacing-xl); +} + +/* .message-wrap :global(pre[class*="language-"]), + .message-wrap :global(pre) { + border: none; + background: none; + position: relative; + direction: ltr; + white-space: no-wrap; + overflow-x: auto; + } + .message-wrap :global(code) { + } */ + +/* .message-wrap :global(div[class*="code_wrap"]) { + + } */ + +.md code, +.md pre { + background: none; + font-family: var(--font-mono); + font-size: var(--text-sm); + + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + tab-size: 2; + + hyphens: none; +} + +.md pre[class*="language-"]::-moz-selection, +.md pre[class*="language-"] ::-moz-selection, +.md code[class*="language-"]::-moz-selection, +.md code[class*="language-"] ::-moz-selection { +} + +.md pre[class*="language-"]::selection, +.md pre[class*="language-"] ::selection, +.md code[class*="language-"]::selection, +.md code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +/* Code blocks */ +.md pre { + padding: 1em; + margin: 0.5em 0; + overflow: auto; + position: relative; + margin-top: var(--spacing-sm); + margin-bottom: var(--spacing-sm); + box-shadow: none; + border: none; + border-radius: var(--radius-md); + background-color: var(--chatbot-code-background-color); + padding: var(--spacing-lg) var(--spacing-xl); + font-family: var(--font-mono); + /* font-size: var(--text-sm) !important; */ + display: block; + white-space: pre; + border-radius: var(--radius-sm); + text-shadow: none; + border-radius: var(--radius-sm); + /* font-size: 85%; */ + white-space: nowrap; + display: block; + white-space: pre; +} + +.prose code { +} +.prose pre > code { +} + +/* Inline code */ +.md :not(pre) > code[class*="language-"] { + padding: 0.1em; + border-radius: var(--radius-xs); + white-space: normal; +} + +.md .token.comment, +.md .token.prolog, +.md .token.doctype, +.md .token.cdata { + color: slategray; +} + +.md .token.punctuation { + color: #999; +} + +.md .token.namespace { + opacity: 0.7; +} + +.md .token.property, +.md .token.tag, +.md .token.boolean, +.md .token.number, +.md .token.constant, +.md .token.symbol, +.md .token.deleted { + color: #905; +} + +.md .token.selector, +.md .token.attr-name, +.md .token.string, +.md .token.char, +.md .token.builtin, +.md .token.inserted { + color: #690; +} + +.md .token.atrule, +.md .token.attr-value, +.md .token.keyword { + color: #07a; +} + +.md .token.function, +.md .token.class-name { + color: #dd4a68; +} + +.md .token.regex, +.md .token.important, +.md .token.variable { + color: #e90; +} + +.md .token.important, +.md .token.bold { + font-weight: bold; +} +.md .token.italic { + font-style: italic; +} + +.md .token.entity { + cursor: help; +} + +.dark .md .token.comment, +.dark .md .token.prolog, +.dark .md .token.cdata { + color: hsl(220, 10%, 40%); +} + +.dark .md .token.doctype, +.dark .md .token.punctuation, +.dark .md .token.entity { + color: hsl(220, 14%, 71%); +} + +.dark .md .token.attr-name, +.dark .md .token.class-name, +.dark .md .token.boolean, +.dark .md .token.constant, +.dark .md .token.number, +.dark .md .token.atrule { + color: hsl(29, 54%, 61%); +} + +.dark .md .token.keyword { + color: hsl(286, 60%, 67%); +} + +.dark .md .token.property, +.dark .md .token.tag, +.dark .md .token.symbol, +.dark .md .token.deleted, +.dark .md .token.important { + color: hsl(355, 65%, 65%); +} + +.dark .md .token.selector, +.dark .md .token.string, +.dark .md .token.char, +.dark .md .token.builtin, +.dark .md .token.inserted, +.dark .md .token.regex, +.dark .md .token.attr-value, +.dark .md .token.attr-value > .token.punctuation { + color: hsl(95, 38%, 62%); +} + +.dark .md .token.variable, +.dark .md .token.operator, +.dark .md .token.function { + color: hsl(207, 82%, 66%); +} + +.dark .md .token.url { + color: hsl(187, 47%, 55%); +} diff --git a/js/markdown/static/utils.ts b/js/markdown/static/utils.ts new file mode 100644 index 000000000000..afdc1afb2f8b --- /dev/null +++ b/js/markdown/static/utils.ts @@ -0,0 +1,193 @@ +import { marked, type Renderer } from "marked"; +import { markedHighlight } from "marked-highlight"; +import Prism from "prismjs"; +import "prismjs/components/prism-python"; +import "prismjs/components/prism-latex"; +// import loadLanguages from "prismjs/components/"; + +// loadLanguages(["python", "latex"]); + +import type { ActionReturn } from "svelte/action"; + +const COPY_ICON_CODE = ``; +const CHECK_ICON_CODE = ``; +const COPY_BUTTON_CODE = ``; + +const escape_test = /[&<>"']/; +const escape_replace = new RegExp(escape_test.source, "g"); +const escape_test_no_encode = + /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/; +const escape_replace_no_encode = new RegExp(escape_test_no_encode.source, "g"); +const escape_replacements: Record = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'" +}; + +const get_escape_replacement = (ch: string): string => + escape_replacements[ch] || ""; + +function escape(html: string, encode?: boolean): string { + if (encode) { + if (escape_test.test(html)) { + return html.replace(escape_replace, get_escape_replacement); + } + } else { + if (escape_test_no_encode.test(html)) { + return html.replace(escape_replace_no_encode, get_escape_replacement); + } + } + + return html; +} + +const renderer: Partial> = { + code( + this: Renderer, + code: string, + infostring: string | undefined, + escaped: boolean + ) { + const lang = (infostring ?? "").match(/\S*/)?.[0] ?? ""; + if (this.options.highlight) { + const out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + code = code.replace(/\n$/, "") + "\n"; + + if (!lang) { + return ( + '
' + + COPY_BUTTON_CODE + + "
" +
+				(escaped ? code : escape(code, true)) +
+				"
\n" + ); + } + + return ( + '
' + + COPY_BUTTON_CODE + + '
' +
+			(escaped ? code : escape(code, true)) +
+			"
\n" + ); + } +}; + +marked.use( + { + gfm: true, + breaks: true, + pedantic: false, + headerIds: false, + mangle: false + }, + markedHighlight({ + highlight: (code: string, lang: string) => { + if (Prism.languages[lang]) { + return Prism.highlight(code, Prism.languages[lang], lang); + } + return code; + } + }), + { renderer } +); + +export function copy(node: HTMLDivElement): ActionReturn { + node.addEventListener("click", handle_copy); + + async function handle_copy(event: MouseEvent): Promise { + const path = event.composedPath() as HTMLButtonElement[]; + + const [copy_button] = path.filter( + (e) => e?.tagName === "BUTTON" && e.classList.contains("copy_code_button") + ); + + if (copy_button) { + event.stopImmediatePropagation(); + + const copy_text = copy_button.parentElement!.innerText.trim(); + const copy_sucess_button = Array.from( + copy_button.children + )[1] as HTMLDivElement; + + const copied = await copy_to_clipboard(copy_text); + + if (copied) copy_feedback(copy_sucess_button); + + function copy_feedback(_copy_sucess_button: HTMLDivElement): void { + _copy_sucess_button.style.opacity = "1"; + setTimeout(() => { + _copy_sucess_button.style.opacity = "0"; + }, 2000); + } + } + } + + return { + destroy(): void { + node.removeEventListener("click", handle_copy); + } + }; +} + +async function copy_to_clipboard(value: string): Promise { + let copied = false; + if ("clipboard" in navigator) { + await navigator.clipboard.writeText(value); + copied = true; + } else { + const textArea = document.createElement("textarea"); + textArea.value = value; + + textArea.style.position = "absolute"; + textArea.style.left = "-999999px"; + + document.body.prepend(textArea); + textArea.select(); + + try { + document.execCommand("copy"); + copied = true; + } catch (error) { + console.error(error); + copied = false; + } finally { + textArea.remove(); + } + } + + return copied; +} + +export { marked }; diff --git a/js/model3D/interactive/InteractiveModel3d.svelte b/js/model3D/interactive/InteractiveModel3d.svelte index b244427957b6..29896b552db6 100644 --- a/js/model3D/interactive/InteractiveModel3d.svelte +++ b/js/model3D/interactive/InteractiveModel3d.svelte @@ -1,4 +1,5 @@ gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:submit={() => gradio.dispatch("submit")} + on:blur={() => gradio.dispatch("blur")} + on:focus={() => gradio.dispatch("focus")} /> diff --git a/js/number/package.json b/js/number/package.json index 7eb336df63ba..b460a6c280ad 100644 --- a/js/number/package.json +++ b/js/number/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@gradio/atoms": "workspace:^", - "@gradio/statustracker": "workspace:^" + "@gradio/statustracker": "workspace:^", + "@gradio/utils": "workspace:^" } } diff --git a/js/number/static/StaticNumber.svelte b/js/number/static/StaticNumber.svelte index e4798dc87466..76cc906a2589 100644 --- a/js/number/static/StaticNumber.svelte +++ b/js/number/static/StaticNumber.svelte @@ -1,4 +1,5 @@ gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:submit={() => gradio.dispatch("submit")} + on:blur={() => gradio.dispatch("blur")} + on:focus={() => gradio.dispatch("focus")} /> diff --git a/js/plot/static/StaticPlot.svelte b/js/plot/static/StaticPlot.svelte index 4757414192f5..1e612ad6fa8f 100644 --- a/js/plot/static/StaticPlot.svelte +++ b/js/plot/static/StaticPlot.svelte @@ -1,4 +1,5 @@ - + gradio.dispatch("change")} + /> diff --git a/js/radio/interactive/InteractiveRadio.svelte b/js/radio/interactive/InteractiveRadio.svelte index 6bbc0f85c752..5d80628c63da 100644 --- a/js/radio/interactive/InteractiveRadio.svelte +++ b/js/radio/interactive/InteractiveRadio.svelte @@ -1,4 +1,5 @@ gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:select={(e) => gradio.dispatch("select", e.detail)} /> diff --git a/js/radio/static/Radio.svelte b/js/radio/static/Radio.svelte index 28c5f7c11396..9bce8fa69832 100644 --- a/js/radio/static/Radio.svelte +++ b/js/radio/static/Radio.svelte @@ -1,4 +1,5 @@ gradio.dispatch("change")} + on:input={() => gradio.dispatch("input")} + on:select={(e) => gradio.dispatch("select", e.detail)} /> diff --git a/js/slider/Slider.component.spec.ts b/js/slider/Slider.component.spec.ts index 1e9154a80233..36aea0a97d52 100644 --- a/js/slider/Slider.component.spec.ts +++ b/js/slider/Slider.component.spec.ts @@ -75,7 +75,10 @@ test("Slider respects show_label", async ({ mount, page }) => { show_label: false, step: 1, mode: "dynamic", - loading_status: loading_status + loading_status: loading_status, + gradio: { + dispatch() {} + } } }); await expect(component.getByTestId("block-title")).toBeHidden(); @@ -91,7 +94,10 @@ test("Slider Maximum/Minimum values", async ({ mount, page }) => { show_label: true, step: 1, mode: "dynamic", - loading_status: loading_status + loading_status: loading_status, + gradio: { + dispatch() {} + } } }); const slider = component.getByLabel("My Slider"); @@ -102,8 +108,15 @@ test("Slider Maximum/Minimum values", async ({ mount, page }) => { }); test("Slider Change event", async ({ mount, page }) => { - let change = spy(); - let release = spy(); + const events = { + change: 0, + release: 0 + }; + + function event(name: "change" | "release") { + events[name] += 1; + } + const component = await mount(Slider, { props: { value: 3, @@ -113,11 +126,10 @@ test("Slider Change event", async ({ mount, page }) => { show_label: true, step: 1, mode: "dynamic", - loading_status: loading_status - }, - on: { - change: change, - release: release + loading_status: loading_status, + gradio: { + dispatch: event + } } }); @@ -127,6 +139,6 @@ test("Slider Change event", async ({ mount, page }) => { await expect(component.getByLabel("My Slider")).toHaveValue("7"); // More than one change event and one release event. - await expect(change.callCount).toBeGreaterThan(1); - await expect(release.callCount).toEqual(1); + await expect(events.change).toBeGreaterThanOrEqual(1); + await expect(events.release).toBeGreaterThanOrEqual(1); }); diff --git a/js/slider/interactive/InteractiveSlider.svelte b/js/slider/interactive/InteractiveSlider.svelte index b8d2ceb8dc8d..946095d8aaf7 100644 --- a/js/slider/interactive/InteractiveSlider.svelte +++ b/js/slider/interactive/InteractiveSlider.svelte @@ -1,4 +1,5 @@ @@ -35,8 +41,8 @@ {minimum} {maximum} {step} - on:input - on:change - on:release + on:input={() => gradio.dispatch("input")} + on:change={() => gradio.dispatch("change")} + on:release={(e) => gradio.dispatch("release", e.detail)} /> diff --git a/js/slider/package.json b/js/slider/package.json index 78d48bf2a110..c067e71de25c 100644 --- a/js/slider/package.json +++ b/js/slider/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@gradio/atoms": "workspace:^", - "@gradio/statustracker": "workspace:^" + "@gradio/statustracker": "workspace:^", + "@gradio/utils": "workspace:^" } } diff --git a/js/slider/static/StaticSlider.svelte b/js/slider/static/StaticSlider.svelte index d81bc10571a4..5e7c51cd490c 100644 --- a/js/slider/static/StaticSlider.svelte +++ b/js/slider/static/StaticSlider.svelte @@ -1,4 +1,5 @@ @@ -36,8 +42,8 @@ {maximum} {step} disabled - on:input - on:change - on:release + on:input={() => gradio.dispatch("input")} + on:change={() => gradio.dispatch("change")} + on:release={(e) => gradio.dispatch("release", e.detail)} /> diff --git a/js/tabitem/static/StaticTabItem.svelte b/js/tabitem/static/StaticTabItem.svelte index 7af11bcda0a4..ba52196b4608 100644 --- a/js/tabitem/static/StaticTabItem.svelte +++ b/js/tabitem/static/StaticTabItem.svelte @@ -1,12 +1,22 @@ - + gradio.dispatch("select", detail)} +> diff --git a/js/tabs/static/StaticTabs.svelte b/js/tabs/static/StaticTabs.svelte index 9ae3b598acc5..383f0913a0ef 100644 --- a/js/tabs/static/StaticTabs.svelte +++ b/js/tabs/static/StaticTabs.svelte @@ -1,4 +1,5 @@ - + gradio.dispatch("change")} + on:select={(e) => gradio.dispatch("select", e.detail)} +> diff --git a/js/textbox/Textbox.test.ts b/js/textbox/Textbox.test.ts index ce5a0c3d5428..dd1f45ea364c 100644 --- a/js/textbox/Textbox.test.ts +++ b/js/textbox/Textbox.test.ts @@ -6,14 +6,15 @@ import event from "@testing-library/user-event"; import Textbox from "./interactive"; import type { LoadingStatus } from "@gradio/statustracker"; -const loading_status = { +const loading_status: LoadingStatus = { eta: 0, queue_position: 1, queue_size: 1, status: "complete" as LoadingStatus["status"], scroll_to_output: false, visible: true, - fn_index: 0 + fn_index: 0, + show_progress: "full" }; describe("Textbox", () => { @@ -25,7 +26,6 @@ describe("Textbox", () => { max_lines: 1, loading_status, lines: 1, - mode: "dynamic", value: "hello world", label: "Textbox" }); @@ -37,20 +37,18 @@ describe("Textbox", () => { }); test("changing the text should update the value", async () => { - const { component, getByDisplayValue } = await render(Textbox, { + const { component, getByDisplayValue, listen } = await render(Textbox, { show_label: true, max_lines: 10, loading_status, lines: 1, - mode: "dynamic", value: "hi ", label: "Textbox" }); const item: HTMLInputElement = getByDisplayValue("hi") as HTMLInputElement; - const mock = spy(); - component.$on("change", mock); + const mock = listen("change"); item.focus(); await event.keyboard("some text"); @@ -58,6 +56,6 @@ describe("Textbox", () => { assert.equal(item.value, "hi some text"); assert.equal(component.value, "hi some text"); assert.equal(mock.callCount, 9); - assert.equal(mock.calls[8][0].detail, "hi some text"); + assert.equal(mock.calls[8][0].detail.data, "hi some text"); }); }); diff --git a/js/textbox/interactive/InteractiveTextbox.svelte b/js/textbox/interactive/InteractiveTextbox.svelte index 84665d4f3828..cbc6d11c6cd3 100644 --- a/js/textbox/interactive/InteractiveTextbox.svelte +++ b/js/textbox/interactive/InteractiveTextbox.svelte @@ -1,11 +1,21 @@ { export async function render< Events extends Record, Props extends Record, - T extends SvelteComponent + T extends SvelteComponent, + X extends Record >( Component: ComponentType | { default: ComponentType }, - props?: Props -): Promise> { + props?: Omit +): Promise< + RenderResult & { + listen: typeof listen; + wait_for_event: typeof wait_for_event; + } +> { const container = document.body; const target = container.appendChild(document.createElement("div")); - const ComponentConstructor: ComponentType = + const ComponentConstructor: ComponentType< + T, + Props & { gradio: typeof Gradio } + > = //@ts-ignore Component.default || Component; + const id = Math.floor(Math.random() * 1000000); + const component = new ComponentConstructor({ target, - props + //@ts-ignore + props: { + ...(props || {}), + gradio: new Gradio(id, target, "light", "2.0.0", "http://localhost:8000") + } }); containerCache.set(container, { target, component }); @@ -66,6 +83,36 @@ export async function render< await tick(); + type extractGeneric = Type extends Gradio ? X : null; + type event_name = keyof extractGeneric; + + function listen(event: event_name): Spy { + const mock = spy(); + target.addEventListener("gradio", (e: Event) => { + if (isCustomEvent(e)) { + if (e.detail.event === event && e.detail.id === id) { + mock(e); + } + } + }); + + return mock; + } + + async function wait_for_event(event: event_name): Promise { + return new Promise((res) => { + const mock = spy(); + target.addEventListener("gradio", (e: Event) => { + if (isCustomEvent(e)) { + if (e.detail.event === event && e.detail.id === id) { + mock(e); + res(mock); + } + } + }); + }); + } + return { container, component, @@ -74,7 +121,9 @@ export async function render< unmount: (): void => { if (componentCache.has(component)) component.$destroy(); }, - ...getQueriesForElement(container) + ...getQueriesForElement(container), + listen, + wait_for_event }; } @@ -115,3 +164,7 @@ export type FireFunction = ( ) => Promise; export * from "@testing-library/dom"; + +function isCustomEvent(event: Event): event is CustomEvent { + return "detail" in event; +} diff --git a/js/upload/src/index.ts b/js/upload/src/index.ts index fe7e997aa8cd..e6539f0187b2 100644 --- a/js/upload/src/index.ts +++ b/js/upload/src/index.ts @@ -1,4 +1,8 @@ export { default as Upload } from "./Upload.svelte"; export { default as ModifyUpload } from "./ModifyUpload.svelte"; export type { FileData } from "./types"; -export {normalise_file, get_fetchable_url_or_file, blobToBase64} from "./utils"; +export { + normalise_file, + get_fetchable_url_or_file, + blobToBase64 +} from "./utils"; diff --git a/js/upload/src/utils.ts b/js/upload/src/utils.ts index 3cfc17d183c1..687451b532e2 100644 --- a/js/upload/src/utils.ts +++ b/js/upload/src/utils.ts @@ -55,20 +55,24 @@ export function normalise_file( function is_url(str: string): boolean { try { - const url = new URL(str); - return url.protocol === "http:" || url.protocol === "https:"; + const url = new URL(str); + return url.protocol === "http:" || url.protocol === "https:"; } catch { - return false; + return false; } - } - -export function get_fetchable_url_or_file(path: string | null, root: string, root_url: string | null): string { +} + +export function get_fetchable_url_or_file( + path: string | null, + root: string, + root_url: string | null +): string { if (path == null) { return root_url ? `/proxy=${root_url}file=` : `${root}/file=`; - } + } if (is_url(path)) { return path; - } + } return root_url ? `/proxy=${root_url}file=${path}` : `${root}/file=${path}`; } diff --git a/js/uploadbutton/UploadButton.test.ts b/js/uploadbutton/UploadButton.test.ts index ce8e6d301be9..79b9336f4fa2 100644 --- a/js/uploadbutton/UploadButton.test.ts +++ b/js/uploadbutton/UploadButton.test.ts @@ -25,7 +25,6 @@ describe("UploadButton", () => { const { getByTestId } = await render(UploadButton, { label: "file", value: null, - mode: "dynamic", root: "http://localhost:7860", file_count: "1" }); @@ -47,18 +46,20 @@ describe("UploadButton", () => { await import("@gradio/client"); setupi18n(); - const { component, getByTestId } = await render(UploadButton, { - label: "file", - value: null, - mode: "dynamic", - root: "http://localhost:7860", - file_count: "1" - }); + const { component, getByTestId, wait_for_event } = await render( + UploadButton, + { + label: "file", + value: null, + root: "http://localhost:7860", + file_count: "1" + } + ); const item = getByTestId("file-upload-button"); //container.querySelectorAll("input")[0]; const file = new File(["hello"], "my-audio.wav", { type: "audio/wav" }); event.upload(item, file); - const mock = await wait_for_event(component, "change"); + const mock = await wait_for_event("change"); expect(mock.callCount).toBe(1); const [data] = component.$capture_state().value; expect(data).toBeTruthy(); diff --git a/js/uploadbutton/interactive/InteractiveUploadButton.svelte b/js/uploadbutton/interactive/InteractiveUploadButton.svelte index d5fdacca8c70..032ec0c44d9e 100644 --- a/js/uploadbutton/interactive/InteractiveUploadButton.svelte +++ b/js/uploadbutton/interactive/InteractiveUploadButton.svelte @@ -1,5 +1,6 @@ gradio.dispatch("click")} on:load={handle_upload} > {$_(label)} diff --git a/js/uploadbutton/package.json b/js/uploadbutton/package.json index 94c419a1837c..e1ab97472ddb 100644 --- a/js/uploadbutton/package.json +++ b/js/uploadbutton/package.json @@ -17,6 +17,7 @@ "dependencies": { "@gradio/button": "workspace:^", "@gradio/client": "workspace:^", - "@gradio/upload": "workspace:^" + "@gradio/upload": "workspace:^", + "@gradio/utils": "workspace:^" } } diff --git a/js/uploadbutton/static/StaticUploadButton.svelte b/js/uploadbutton/static/StaticUploadButton.svelte index 5a943d4ccb0e..e57208583eb3 100644 --- a/js/uploadbutton/static/StaticUploadButton.svelte +++ b/js/uploadbutton/static/StaticUploadButton.svelte @@ -1,5 +1,6 @@ gradio.dispatch("click")} on:load={handle_upload} > {$_(label)} diff --git a/js/utils/src/index.ts b/js/utils/src/index.ts index e0127e6bee13..481e1f1ee755 100644 --- a/js/utils/src/index.ts +++ b/js/utils/src/index.ts @@ -1,2 +1,3 @@ export * from "./color"; export * from "./utils"; +export * from "./types"; diff --git a/js/utils/src/types.ts b/js/utils/src/types.ts new file mode 100644 index 000000000000..904c904c2c21 --- /dev/null +++ b/js/utils/src/types.ts @@ -0,0 +1 @@ +export { type Gradio } from "../../app/src/gradio_helper"; diff --git a/js/utils/src/utils.ts b/js/utils/src/utils.ts index 8140df529aa7..e32ee9fb2a35 100644 --- a/js/utils/src/utils.ts +++ b/js/utils/src/utils.ts @@ -1,3 +1,4 @@ +import { type ActionReturn } from "svelte/action"; export interface SelectData { index: number | [number, number]; value: any; @@ -76,3 +77,70 @@ function dataURLtoBlob(dataurl: string): Blob { } return new Blob([u8arr], { type: mime }); } + +export function copy(node: HTMLDivElement): ActionReturn { + node.addEventListener("click", handle_copy); + + async function handle_copy(event: MouseEvent): Promise { + const path = event.composedPath() as HTMLButtonElement[]; + + const [copy_button] = path.filter( + (e) => e?.tagName === "BUTTON" && e.classList.contains("copy_code_button") + ); + + if (copy_button) { + event.stopImmediatePropagation(); + + const copy_text = copy_button.parentElement!.innerText.trim(); + const copy_sucess_button = Array.from( + copy_button.children + )[1] as HTMLDivElement; + + const copied = await copy_to_clipboard(copy_text); + + if (copied) copy_feedback(copy_sucess_button); + + function copy_feedback(_copy_sucess_button: HTMLDivElement): void { + _copy_sucess_button.style.opacity = "1"; + setTimeout(() => { + _copy_sucess_button.style.opacity = "0"; + }, 2000); + } + } + } + + return { + destroy(): void { + node.removeEventListener("click", handle_copy); + } + }; +} + +async function copy_to_clipboard(value: string): Promise { + let copied = false; + if ("clipboard" in navigator) { + await navigator.clipboard.writeText(value); + copied = true; + } else { + const textArea = document.createElement("textarea"); + textArea.value = value; + + textArea.style.position = "absolute"; + textArea.style.left = "-999999px"; + + document.body.prepend(textArea); + textArea.select(); + + try { + document.execCommand("copy"); + copied = true; + } catch (error) { + console.error(error); + copied = false; + } finally { + textArea.remove(); + } + } + + return copied; +} diff --git a/js/video/Video.test.ts b/js/video/Video.test.ts index 15d60d5db79a..e54dca8fa6b6 100644 --- a/js/video/Video.test.ts +++ b/js/video/Video.test.ts @@ -55,7 +55,7 @@ describe("Video", () => { name: "bar", source: "upload" }); - let vid = getByTestId("Test Label-player") as HTMLVideoElement + let vid = getByTestId("Test Label-player") as HTMLVideoElement; assert.equal( vid.src, "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav" @@ -101,7 +101,7 @@ describe("Video", () => { name: "bar", source: "upload" }); - let vid = getByTestId("test-player") as HTMLVideoElement + let vid = getByTestId("test-player") as HTMLVideoElement; assert.equal( vid.src, "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav" @@ -252,7 +252,7 @@ describe("Video", () => { }); test("video change event trigger fires when value is changed and only fires once", async () => { - const { component } = await render(InteractiveVideo, { + const { component, listen } = await render(InteractiveVideo, { show_label: true, loading_status, mode: "dynamic", @@ -271,8 +271,7 @@ describe("Video", () => { autoplay: true }); - const mock = spy(); - component.$on("change", mock); + const mock = listen("change"); (component.value = [ { diff --git a/js/video/interactive/InteractiveVideo.svelte b/js/video/interactive/InteractiveVideo.svelte index 94961755a068..a889965d6b3f 100644 --- a/js/video/interactive/InteractiveVideo.svelte +++ b/js/video/interactive/InteractiveVideo.svelte @@ -1,7 +1,7 @@ @@ -100,14 +107,14 @@ {mirror_webcam} {include_audio} {autoplay} - on:clear - on:play - on:pause - on:upload - on:stop - on:end - on:start_recording - on:stop_recording + on:clear={() => gradio.dispatch("clear")} + on:play={() => gradio.dispatch("play")} + on:pause={() => gradio.dispatch("pause")} + on:upload={() => gradio.dispatch("upload")} + on:stop={() => gradio.dispatch("stop")} + on:end={() => gradio.dispatch("end")} + on:start_recording={() => gradio.dispatch("start_recording")} + on:stop_recording={() => gradio.dispatch("stop_recording")} > diff --git a/js/video/static/StaticVideo.svelte b/js/video/static/StaticVideo.svelte index 26b3ce736ecc..f6faaaadc55d 100644 --- a/js/video/static/StaticVideo.svelte +++ b/js/video/static/StaticVideo.svelte @@ -1,7 +1,7 @@ @@ -82,10 +91,11 @@ {show_label} {autoplay} {show_share_button} - on:play - on:pause - on:stop - on:share - on:error + on:play={() => gradio.dispatch("play")} + on:pause={() => gradio.dispatch("pause")} + on:stop={() => gradio.dispatch("stop")} + on:end={() => gradio.dispatch("end")} + on:share={({ detail }) => gradio.dispatch("share", detail)} + on:error={({ detail }) => gradio.dispatch("error", detail)} /> diff --git a/js/video/static/VideoPreview.svelte b/js/video/static/VideoPreview.svelte index d5a3630c9107..13b7e39249a9 100644 --- a/js/video/static/VideoPreview.svelte +++ b/js/video/static/VideoPreview.svelte @@ -55,7 +55,8 @@ {autoplay} on:play on:pause - on:ended + on:stop + on:end mirror={false} {label} /> diff --git a/package.json b/package.json index 6b72e559e8ec..a2302fa89122 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "@csstools/postcss-global-data": "^2.0.0", "@gradio/tootils": "workspace:^", "@manypkg/get-packages": "^2.2.0", - "@playwright/experimental-ct-svelte": "^1.35.1", - "@playwright/test": "^1.35.1", + "@playwright/experimental-ct-svelte": "^1.37.1", + "@playwright/test": "^1.37.1", "@sveltejs/vite-plugin-svelte": "^2.4.2", "@tailwindcss/forms": "^0.5.0", "@testing-library/dom": "^9.0.0", @@ -56,7 +56,6 @@ "autoprefixer": "^10.4.4", "babylonjs": "^5.17.1", "babylonjs-loaders": "^5.17.1", - "dequal": "^2.0.2", "eslint": "^8.46.0", "eslint-plugin-svelte": "^2.32.4", "globals": "^13.20.0", @@ -88,7 +87,6 @@ "vitest": "^0.34.0" }, "devDependencies": { - "@playwright/test": "^1.35.1", "@storybook/addon-a11y": "^7.0.24", "@storybook/addon-essentials": "^7.0.23", "@storybook/addon-interactions": "^7.0.23", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdef67a6a1db..1bc0eb1b8b5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,11 +27,11 @@ importers: specifier: ^2.2.0 version: 2.2.0 '@playwright/experimental-ct-svelte': - specifier: ^1.35.1 - version: 1.35.1(@types/node@20.3.1)(less@4.1.3)(svelte@4.0.0)(vite@4.3.9) + specifier: ^1.37.1 + version: 1.37.1(@types/node@20.3.1)(less@4.1.3)(svelte@4.0.0)(vite@4.3.9) '@playwright/test': - specifier: ^1.35.1 - version: 1.35.1 + specifier: ^1.37.1 + version: 1.37.1 '@sveltejs/vite-plugin-svelte': specifier: ^2.4.2 version: 2.4.2(svelte@4.0.0)(vite@4.3.9) @@ -68,9 +68,6 @@ importers: babylonjs-loaders: specifier: ^5.17.1 version: 5.18.0 - dequal: - specifier: ^2.0.2 - version: 2.0.2 eslint: specifier: ^8.46.0 version: 8.46.0 @@ -139,7 +136,7 @@ importers: version: 3.4.4(@babel/core@7.22.5)(less@4.1.3)(postcss@8.4.27)(svelte@4.0.0) svelte-i18n: specifier: ^3.6.0 - version: 3.6.0(svelte@4.0.0) + version: 3.7.0(svelte@4.0.0) svelte-preprocess: specifier: ^5.0.4 version: 5.0.4(@babel/core@7.22.5)(less@4.1.3)(postcss@8.4.27)(svelte@4.0.0)(typescript@5.1.3) @@ -499,9 +496,6 @@ importers: '@gradio/wasm': specifier: workspace:^ version: link:../wasm - '@playwright/test': - specifier: ^1.35.1 - version: 1.35.1 d3-dsv: specifier: ^3.0.1 version: 3.0.1 @@ -577,6 +571,9 @@ importers: '@gradio/icons': specifier: workspace:^ version: link:../icons + '@gradio/markdown': + specifier: workspace:^ + version: link:../markdown '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker @@ -598,21 +595,6 @@ importers: '@types/prismjs': specifier: 1.26.0 version: 1.26.0 - dompurify: - specifier: ^3.0.3 - version: 3.0.3 - katex: - specifier: ^0.16.7 - version: 0.16.7 - marked: - specifier: ^7.0.0 - version: 7.0.0 - marked-highlight: - specifier: ^2.0.1 - version: 2.0.1(marked@7.0.0) - prismjs: - specifier: 1.29.0 - version: 1.29.0 js/checkbox: dependencies: @@ -694,6 +676,9 @@ importers: '@gradio/upload': specifier: workspace:^ version: link:../upload + '@gradio/utils': + specifier: workspace:^ + version: link:../utils '@lezer/common': specifier: ^1.0.2 version: 1.0.2 @@ -721,6 +706,9 @@ importers: '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker + '@gradio/utils': + specifier: workspace:^ + version: link:../utils js/column: {} @@ -732,6 +720,9 @@ importers: '@gradio/button': specifier: workspace:^ version: link:../button + '@gradio/markdown': + specifier: workspace:^ + version: link:../markdown '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker @@ -863,6 +854,9 @@ importers: '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker + '@gradio/utils': + specifier: workspace:^ + version: link:../utils js/icons: {} @@ -904,6 +898,9 @@ importers: '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker + '@gradio/utils': + specifier: workspace:^ + version: link:../utils js/label: dependencies: @@ -934,12 +931,18 @@ importers: '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker + '@gradio/utils': + specifier: workspace:^ + version: link:../utils '@types/dompurify': specifier: ^3.0.2 version: 3.0.2 '@types/katex': specifier: ^0.16.0 version: 0.16.0 + '@types/prismjs': + specifier: 1.26.0 + version: 1.26.0 dompurify: specifier: ^3.0.3 version: 3.0.3 @@ -949,6 +952,12 @@ importers: marked: specifier: ^7.0.0 version: 7.0.0 + marked-highlight: + specifier: ^2.0.1 + version: 2.0.1(marked@7.0.0) + prismjs: + specifier: 1.29.0 + version: 1.29.0 js/model3D: dependencies: @@ -964,6 +973,9 @@ importers: '@gradio/upload': specifier: workspace:^ version: link:../upload + '@gradio/utils': + specifier: workspace:^ + version: link:../utils babylonjs: specifier: ^4.2.1 version: 4.2.2 @@ -979,6 +991,9 @@ importers: '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker + '@gradio/utils': + specifier: workspace:^ + version: link:../utils js/plot: dependencies: @@ -1039,6 +1054,9 @@ importers: '@gradio/statustracker': specifier: workspace:^ version: link:../statustracker + '@gradio/utils': + specifier: workspace:^ + version: link:../utils js/state: {} @@ -1156,6 +1174,9 @@ importers: '@gradio/upload': specifier: workspace:^ version: link:../upload + '@gradio/utils': + specifier: workspace:^ + version: link:../utils js/utils: dependencies: @@ -4588,13 +4609,13 @@ packages: resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==} dependencies: '@formatjs/intl-localematcher': 0.2.25 - tslib: 2.5.3 + tslib: 2.6.1 dev: false /@formatjs/fast-memoize@1.2.1: resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==} dependencies: - tslib: 2.5.3 + tslib: 2.6.1 dev: false /@formatjs/icu-messageformat-parser@2.1.0: @@ -4602,20 +4623,20 @@ packages: dependencies: '@formatjs/ecma402-abstract': 1.11.4 '@formatjs/icu-skeleton-parser': 1.3.6 - tslib: 2.5.3 + tslib: 2.6.1 dev: false /@formatjs/icu-skeleton-parser@1.3.6: resolution: {integrity: sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==} dependencies: '@formatjs/ecma402-abstract': 1.11.4 - tslib: 2.5.3 + tslib: 2.6.1 dev: false /@formatjs/intl-localematcher@0.2.25: resolution: {integrity: sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==} dependencies: - tslib: 2.5.3 + tslib: 2.6.1 dev: false /@humanwhocodes/config-array@0.11.10: @@ -4956,12 +4977,13 @@ packages: resolution: {integrity: sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==} dev: false - /@playwright/experimental-ct-core@1.35.1(@types/node@20.3.1)(less@4.1.3): - resolution: {integrity: sha512-NSoUf6JDLeZFy0HiENwA1GkIwZHvg5KrygnZknwWs7O8yksYLsmiuMb09sf2zsZmfYgVen401SNgf3KfekbweA==} + /@playwright/experimental-ct-core@1.37.1(@types/node@20.3.1)(less@4.1.3): + resolution: {integrity: sha512-3OmhDzrIAcVQlyVHmyaVtzcht/OUEH47uvwPh/rQmz/CrvB6zHMxH/7dIo6SCswMbCFkACepbqGmTW4HjW+yeQ==} engines: {node: '>=16'} hasBin: true dependencies: - '@playwright/test': 1.35.1 + '@playwright/test': 1.37.1 + playwright-core: 1.37.1 vite: 4.3.9(@types/node@20.3.1)(less@4.1.3) transitivePeerDependencies: - '@types/node' @@ -4972,12 +4994,12 @@ packages: - terser dev: false - /@playwright/experimental-ct-svelte@1.35.1(@types/node@20.3.1)(less@4.1.3)(svelte@4.0.0)(vite@4.3.9): - resolution: {integrity: sha512-7CV6pXyZMX9IQl0+J9+eNIv1hZj23z9hMA0GHZr7EubkbJvneIB2HsMKgEGxgW/KSGRqPMBNResfl2ShmHgHHQ==} + /@playwright/experimental-ct-svelte@1.37.1(@types/node@20.3.1)(less@4.1.3)(svelte@4.0.0)(vite@4.3.9): + resolution: {integrity: sha512-UwdO4uyDkr57uh1NWe04PFuH0QKnFvb9KioY20pLswt9K1DfTemY1ql/NJFg8cWR8kZlYTxhbazFQv6iAi3JFQ==} engines: {node: '>=16'} hasBin: true dependencies: - '@playwright/experimental-ct-core': 1.35.1(@types/node@20.3.1)(less@4.1.3) + '@playwright/experimental-ct-core': 1.37.1(@types/node@20.3.1)(less@4.1.3) '@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.0.0)(vite@4.3.9) transitivePeerDependencies: - '@types/node' @@ -4991,13 +5013,13 @@ packages: - vite dev: false - /@playwright/test@1.35.1: - resolution: {integrity: sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==} + /@playwright/test@1.37.1: + resolution: {integrity: sha512-bq9zTli3vWJo8S3LwB91U0qDNQDpEXnw7knhxLM0nwDvexQAwx9tO8iKDZSqqneVq+URd/WIoz+BALMqUTgdSg==} engines: {node: '>=16'} hasBin: true dependencies: - '@types/node': 20.3.1 - playwright-core: 1.35.1 + '@types/node': 20.3.2 + playwright-core: 1.37.1 optionalDependencies: fsevents: 2.3.2 dev: false @@ -6371,7 +6393,7 @@ packages: peerDependencies: '@sveltejs/kit': ^1.0.0 dependencies: - '@sveltejs/kit': 1.16.3(svelte@3.59.2)(vite@4.3.9) + '@sveltejs/kit': 1.16.3(svelte@3.57.0)(vite@4.3.5) import-meta-resolve: 3.0.0 dev: true @@ -7870,7 +7892,7 @@ packages: dependencies: '@babel/runtime': 7.22.6 fast-unique-numbers: 6.0.21 - tslib: 2.5.3 + tslib: 2.6.1 worker-factory: 6.0.69 dev: false @@ -8309,7 +8331,7 @@ packages: '@babel/runtime': 7.22.6 dashify: 2.0.0 indefinite-article: 0.0.2 - tslib: 2.5.3 + tslib: 2.6.1 dev: false /compressible@2.0.18: @@ -9777,7 +9799,7 @@ packages: engines: {node: '>=12.20.1'} dependencies: '@babel/runtime': 7.22.6 - tslib: 2.5.3 + tslib: 2.6.1 dev: false /fast-unique-numbers@8.0.6: @@ -10506,7 +10528,7 @@ packages: '@formatjs/ecma402-abstract': 1.11.4 '@formatjs/fast-memoize': 1.2.1 '@formatjs/icu-messageformat-parser': 2.1.0 - tslib: 2.5.3 + tslib: 2.6.1 dev: false /ip@2.0.0: @@ -12216,8 +12238,8 @@ packages: pathe: 1.1.1 dev: false - /playwright-core@1.35.1: - resolution: {integrity: sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==} + /playwright-core@1.37.1: + resolution: {integrity: sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA==} engines: {node: '>=16'} hasBin: true dev: false @@ -13817,12 +13839,12 @@ packages: dependencies: svelte: 4.0.0 - /svelte-i18n@3.6.0(svelte@4.0.0): - resolution: {integrity: sha512-qvvcMqHVCXJ5pHoQR5uGzWAW5vS3qB9mBq+W6veLZ6jkrzZGOziR+wyOUJsc59BupMh+Ae30qjOndFrRU6v5jA==} + /svelte-i18n@3.7.0(svelte@4.0.0): + resolution: {integrity: sha512-kfdJsYsyOE9tFEVtjPXvrUaufXQnbFAI6LsX9vaQP+xm8A5Wao2qQ6pRZmIUCAvXvYQt7aXQ7hK9+NP9AlxehA==} engines: {node: '>= 16'} hasBin: true peerDependencies: - svelte: ^3.25.1 + svelte: ^3 || ^4 dependencies: cli-color: 2.0.3 deepmerge: 4.3.1 @@ -15478,7 +15500,7 @@ packages: '@babel/runtime': 7.22.6 compilerr: 9.0.21 fast-unique-numbers: 6.0.21 - tslib: 2.5.3 + tslib: 2.6.1 dev: false /worker-factory@7.0.8: diff --git a/test/test_files/xray_config.json b/test/test_files/xray_config.json index 5c73b1c4e64b..43361c688db7 100644 --- a/test/test_files/xray_config.json +++ b/test/test_files/xray_config.json @@ -1,476 +1,449 @@ { - "version": "3.40.1", - "mode": "blocks", - "dev_mode": true, - "analytics_enabled": true, - "components": [ - { - "id": 1, - "type": "markdown", - "props": { - "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", - "rtl": false, - "latex_delimiters": [ - { - "left": "$", - "right": "$", - "display": false - } - ], - "name": "markdown", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 2, - "type": "checkboxgroup", - "props": { - "choices": [ - [ - "Covid", - "Covid" - ], - [ - "Malaria", - "Malaria" - ], - [ - "Lung Cancer", - "Lung Cancer" - ] - ], - "value": [], - "label": "Disease to Scan For", - "show_label": true, - "container": true, - "min_width": 160, - "name": "checkboxgroup", - "visible": true - }, - "serializer": "ListStringSerializable", - "api_info": { - "info": { - "type": "array", - "items": { - "type": "string" - } - }, - "serialized_info": false - }, - "example_inputs": { - "raw": [ - "Covid" - ], - "serialized": [ - "Covid" - ] - } - }, - { - "id": 3, - "type": "tabs", - "props": { - "visible": true - } - }, - { - "id": 4, - "type": "tabitem", - "props": { - "label": "X-ray", - "visible": true - } - }, - { - "id": 5, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 6, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 7, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 8, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 9, - "type": "tabitem", - "props": { - "label": "CT Scan", - "visible": true - } - }, - { - "id": 10, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 11, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 12, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 13, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 14, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "", - "type": "text", - "autofocus": false, - "show_copy_button": false, - "container": true, - "rtl": false, - "show_label": true, - "min_width": 160, - "name": "textbox", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 15, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - }, - { - "id": 16, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - } - ], - "css": null, - "title": "Gradio", - "space_id": null, - "enable_queue": null, - "show_error": true, - "show_api": true, - "is_colab": false, - "stylesheets": [ - "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", - "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" - ], - "theme": "default", - "layout": { - "id": 0, - "children": [ - { - "id": 1 - }, - { - "id": 15, - "children": [ - { - "id": 2 - } - ] - }, - { - "id": 3, - "children": [ - { - "id": 4, - "children": [ - { - "id": 5, - "children": [ - { - "id": 6 - }, - { - "id": 7 - } - ] - }, - { - "id": 8 - } - ] - }, - { - "id": 9, - "children": [ - { - "id": 10, - "children": [ - { - "id": 11 - }, - { - "id": 12 - } - ] - }, - { - "id": 13 - } - ] - } - ] - }, - { - "id": 16, - "children": [ - { - "id": 14 - } - ] - } - ] - }, - "dependencies": [ - { - "targets": [ - 8 - ], - "trigger": "click", - "inputs": [ - 2, - 6 - ], - "outputs": [ - 7 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - }, - { - "targets": [ - 13 - ], - "trigger": "click", - "inputs": [ - 2, - 11 - ], - "outputs": [ - 12 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - } - ] -} \ No newline at end of file + "version": "3.40.1", + "mode": "blocks", + "dev_mode": true, + "analytics_enabled": true, + "components": [ + { + "id": 1, + "type": "markdown", + "props": { + "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", + "rtl": false, + "latex_delimiters": [ + { + "left": "$", + "right": "$", + "display": false + } + ], + "name": "markdown", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 2, + "type": "checkboxgroup", + "props": { + "choices": [ + ["Covid", "Covid"], + ["Malaria", "Malaria"], + ["Lung Cancer", "Lung Cancer"] + ], + "value": [], + "label": "Disease to Scan For", + "show_label": true, + "container": true, + "min_width": 160, + "name": "checkboxgroup", + "visible": true + }, + "serializer": "ListStringSerializable", + "api_info": { + "info": { + "type": "array", + "items": { + "type": "string" + } + }, + "serialized_info": false + }, + "example_inputs": { + "raw": ["Covid"], + "serialized": ["Covid"] + } + }, + { + "id": 3, + "type": "tabs", + "props": { + "visible": true + } + }, + { + "id": 4, + "type": "tabitem", + "props": { + "label": "X-ray", + "visible": true + } + }, + { + "id": 5, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": true, + "visible": true + } + }, + { + "id": 6, + "type": "image", + "props": { + "image_mode": "RGB", + "source": "upload", + "tool": "editor", + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "selectable": false, + "show_share_button": false, + "show_download_button": true, + "show_label": true, + "container": true, + "min_width": 160, + "name": "image", + "visible": true + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 7, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "name": "json", + "visible": true + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 8, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "interactive": true, + "name": "button", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 9, + "type": "tabitem", + "props": { + "label": "CT Scan", + "visible": true + } + }, + { + "id": 10, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": true, + "visible": true + } + }, + { + "id": 11, + "type": "image", + "props": { + "image_mode": "RGB", + "source": "upload", + "tool": "editor", + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "selectable": false, + "show_share_button": false, + "show_download_button": true, + "show_label": true, + "container": true, + "min_width": 160, + "name": "image", + "visible": true + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8mJl+fn/9ZWb8/PzWlwv///6wWGbImAPgTEMImIN9gUFCEm/gDALULDN8PAD6atYdCTX9gUNKlj8wZAKUsAOzZz+UMAOsJAP/Z2ccMDA8PD/95eX5NWvsJCOVNQPtfX/8zM8+QePLl38MGBr8JCP+zs9myn/8GBqwpAP/GxgwJCPny78lzYLgjAJ8vAP9fX/+MjMUcAN8zM/9wcM8ZGcATEL+QePdZWf/29uc/P9cmJu9MTDImIN+/r7+/vz8/P8VNQGNugV8AAF9fX8swMNgTAFlDOICAgPNSUnNWSMQ5MBAQEJE3QPIGAM9AQMqGcG9vb6MhJsEdGM8vLx8fH98AANIWAMuQeL8fABkTEPPQ0OM5OSYdGFl5jo+Pj/+pqcsTE78wMFNGQLYmID4dGPvd3UBAQJmTkP+8vH9QUK+vr8ZWSHpzcJMmILdwcLOGcHRQUHxwcK9PT9DQ0O/v70w5MLypoG8wKOuwsP/g4P/Q0IcwKEswKMl8aJ9fX2xjdOtGRs/Pz+Dg4GImIP8gIH0sKEAwKKmTiKZ8aB/f39Wsl+LFt8dgUE9PT5x5aHBwcP+AgP+WltdgYMyZfyywz78AAAAAAAD///8AAP9mZv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAKgALAAAAAA9AEQAAAj/AFEJHEiwoMGDCBMqXMiwocAbBww4nEhxoYkUpzJGrMixogkfGUNqlNixJEIDB0SqHGmyJSojM1bKZOmyop0gM3Oe2liTISKMOoPy7GnwY9CjIYcSRYm0aVKSLmE6nfq05QycVLPuhDrxBlCtYJUqNAq2bNWEBj6ZXRuyxZyDRtqwnXvkhACDV+euTeJm1Ki7A73qNWtFiF+/gA95Gly2CJLDhwEHMOUAAuOpLYDEgBxZ4GRTlC1fDnpkM+fOqD6DDj1aZpITp0dtGCDhr+fVuCu3zlg49ijaokTZTo27uG7Gjn2P+hI8+PDPERoUB318bWbfAJ5sUNFcuGRTYUqV/3ogfXp1rWlMc6awJjiAAd2fm4ogXjz56aypOoIde4OE5u/F9x199dlXnnGiHZWEYbGpsAEA3QXYnHwEFliKAgswgJ8LPeiUXGwedCAKABACCN+EA1pYIIYaFlcDhytd51sGAJbo3onOpajiihlO92KHGaUXGwWjUBChjSPiWJuOO/LYIm4v1tXfE6J4gCSJEZ7YgRYUNrkji9P55sF/ogxw5ZkSqIDaZBV6aSGYq/lGZplndkckZ98xoICbTcIJGQAZcNmdmUc210hs35nCyJ58fgmIKX5RQGOZowxaZwYA+JaoKQwswGijBV4C6SiTUmpphMspJx9unX4KaimjDv9aaXOEBteBqmuuxgEHoLX6Kqx+yXqqBANsgCtit4FWQAEkrNbpq7HSOmtwag5w57GrmlJBASEU18ADjUYb3ADTinIttsgSB1oJFfA63bduimuqKB1keqwUhoCSK374wbujvOSu4QG6UvxBRydcpKsav++Ca6G8A6Pr1x2kVMyHwsVxUALDq/krnrhPSOzXG1lUTIoffqGR7Goi2MAxbv6O2kEG56I7CSlRsEFKFVyovDJoIRTg7sugNRDGqCJzJgcKE0ywc0ELm6KBCCJo8DIPFeCWNGcyqNFE06ToAfV0HBRgxsvLThHn1oddQMrXj5DyAQgjEHSAJMWZwS3HPxT/QMbabI/iBCliMLEJKX2EEkomBAUCxRi42VDADxyTYDVogV+wSChqmKxEKCDAYFDFj4OmwbY7bDGdBhtrnTQYOigeChUmc1K3QTnAUfEgGFgAWt88hKA6aCRIXhxnQ1yg3BCayK44EWdkUQcBByEQChFXfCB776aQsG0BIlQgQgE8qO26X1h8cEUep8ngRBnOy74E9QgRgEAC8SvOfQkh7FDBDmS43PmGoIiKUUEGkMEC/PJHgxw0xH74yx/3XnaYRJgMB8obxQW6kL9QYEJ0FIFgByfIL7/IQAlvQwEpnAC7DtLNJCKUoO/w45c44GwCXiAFB/OXAATQryUxdN4LfFiwgjCNYg+kYMIEFkCKDs6PKAIJouyGWMS1FSKJOMRB/BoIxYJIUXFUxNwoIkEKPAgCBZSQHQ1A2EWDfDEUVLyADj5AChSIQW6gu10bE/JG2VnCZGfo4R4d0sdQoBAHhPjhIB94v/wRoRKQWGRHgrhGSQJxCS+0pCZbEhAAOw==", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 12, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "name": "json", + "visible": true + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 13, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "interactive": true, + "name": "button", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 14, + "type": "textbox", + "props": { + "lines": 1, + "max_lines": 20, + "value": "", + "type": "text", + "autofocus": false, + "show_copy_button": false, + "container": true, + "rtl": false, + "show_label": true, + "min_width": 160, + "name": "textbox", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 15, + "type": "form", + "props": { + "type": "form", + "scale": 0, + "min_width": 0, + "visible": true + } + }, + { + "id": 16, + "type": "form", + "props": { + "type": "form", + "scale": 0, + "min_width": 0, + "visible": true + } + } + ], + "css": null, + "title": "Gradio", + "space_id": null, + "enable_queue": null, + "show_error": true, + "show_api": true, + "is_colab": false, + "stylesheets": [ + "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", + "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" + ], + "theme": "default", + "layout": { + "id": 0, + "children": [ + { + "id": 1 + }, + { + "id": 15, + "children": [ + { + "id": 2 + } + ] + }, + { + "id": 3, + "children": [ + { + "id": 4, + "children": [ + { + "id": 5, + "children": [ + { + "id": 6 + }, + { + "id": 7 + } + ] + }, + { + "id": 8 + } + ] + }, + { + "id": 9, + "children": [ + { + "id": 10, + "children": [ + { + "id": 11 + }, + { + "id": 12 + } + ] + }, + { + "id": 13 + } + ] + } + ] + }, + { + "id": 16, + "children": [ + { + "id": 14 + } + ] + } + ] + }, + "dependencies": [ + { + "targets": [8], + "trigger": "click", + "inputs": [2, 6], + "outputs": [7], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [13], + "trigger": "click", + "inputs": [2, 11], + "outputs": [12], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + } + ] +} diff --git a/test/test_files/xray_config_diff_ids.json b/test/test_files/xray_config_diff_ids.json index 132f4eb19e60..dfb5cddf235b 100644 --- a/test/test_files/xray_config_diff_ids.json +++ b/test/test_files/xray_config_diff_ids.json @@ -1,476 +1,449 @@ { - "version": "3.40.1", - "mode": "blocks", - "dev_mode": true, - "analytics_enabled": true, - "components": [ - { - "id": 101, - "type": "markdown", - "props": { - "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", - "rtl": false, - "latex_delimiters": [ - { - "left": "$", - "right": "$", - "display": false - } - ], - "name": "markdown", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 102, - "type": "checkboxgroup", - "props": { - "choices": [ - [ - "Covid", - "Covid" - ], - [ - "Malaria", - "Malaria" - ], - [ - "Lung Cancer", - "Lung Cancer" - ] - ], - "value": [], - "label": "Disease to Scan For", - "show_label": true, - "container": true, - "min_width": 160, - "name": "checkboxgroup", - "visible": true - }, - "serializer": "ListStringSerializable", - "api_info": { - "info": { - "type": "array", - "items": { - "type": "string" - } - }, - "serialized_info": false - }, - "example_inputs": { - "raw": [ - "Covid" - ], - "serialized": [ - "Covid" - ] - } - }, - { - "id": 103, - "type": "tabs", - "props": { - "visible": true - } - }, - { - "id": 104, - "type": "tabitem", - "props": { - "label": "X-ray", - "visible": true - } - }, - { - "id": 105, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 106, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 107, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 108, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 109, - "type": "tabitem", - "props": { - "label": "CT Scan", - "visible": true - } - }, - { - "id": 110, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 111, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 112, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 113, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 114, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "", - "type": "text", - "autofocus": false, - "show_copy_button": false, - "container": true, - "rtl": false, - "show_label": true, - "min_width": 160, - "name": "textbox", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 115, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - }, - { - "id": 116, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - } - ], - "css": null, - "title": "Gradio", - "space_id": null, - "enable_queue": null, - "show_error": true, - "show_api": true, - "is_colab": false, - "stylesheets": [ - "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", - "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" - ], - "theme": "default", - "layout": { - "id": 100, - "children": [ - { - "id": 101 - }, - { - "id": 115, - "children": [ - { - "id": 102 - } - ] - }, - { - "id": 103, - "children": [ - { - "id": 104, - "children": [ - { - "id": 105, - "children": [ - { - "id": 106 - }, - { - "id": 107 - } - ] - }, - { - "id": 108 - } - ] - }, - { - "id": 109, - "children": [ - { - "id": 110, - "children": [ - { - "id": 111 - }, - { - "id": 112 - } - ] - }, - { - "id": 113 - } - ] - } - ] - }, - { - "id": 116, - "children": [ - { - "id": 114 - } - ] - } - ] - }, - "dependencies": [ - { - "targets": [ - 108 - ], - "trigger": "click", - "inputs": [ - 102, - 106 - ], - "outputs": [ - 107 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - }, - { - "targets": [ - 113 - ], - "trigger": "click", - "inputs": [ - 102, - 111 - ], - "outputs": [ - 112 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - } - ] -} \ No newline at end of file + "version": "3.40.1", + "mode": "blocks", + "dev_mode": true, + "analytics_enabled": true, + "components": [ + { + "id": 101, + "type": "markdown", + "props": { + "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", + "rtl": false, + "latex_delimiters": [ + { + "left": "$", + "right": "$", + "display": false + } + ], + "name": "markdown", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 102, + "type": "checkboxgroup", + "props": { + "choices": [ + ["Covid", "Covid"], + ["Malaria", "Malaria"], + ["Lung Cancer", "Lung Cancer"] + ], + "value": [], + "label": "Disease to Scan For", + "show_label": true, + "container": true, + "min_width": 160, + "name": "checkboxgroup", + "visible": true + }, + "serializer": "ListStringSerializable", + "api_info": { + "info": { + "type": "array", + "items": { + "type": "string" + } + }, + "serialized_info": false + }, + "example_inputs": { + "raw": ["Covid"], + "serialized": ["Covid"] + } + }, + { + "id": 103, + "type": "tabs", + "props": { + "visible": true + } + }, + { + "id": 104, + "type": "tabitem", + "props": { + "label": "X-ray", + "visible": true + } + }, + { + "id": 105, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": true, + "visible": true + } + }, + { + "id": 106, + "type": "image", + "props": { + "image_mode": "RGB", + "source": "upload", + "tool": "editor", + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "selectable": false, + "show_share_button": false, + "show_download_button": true, + "show_label": true, + "container": true, + "min_width": 160, + "name": "image", + "visible": true + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 107, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "name": "json", + "visible": true + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 108, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "interactive": true, + "name": "button", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 109, + "type": "tabitem", + "props": { + "label": "CT Scan", + "visible": true + } + }, + { + "id": 110, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": true, + "visible": true + } + }, + { + "id": 111, + "type": "image", + "props": { + "image_mode": "RGB", + "source": "upload", + "tool": "editor", + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "selectable": false, + "show_share_button": false, + "show_download_button": true, + "show_label": true, + "container": true, + "min_width": 160, + "name": "image", + "visible": true + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 112, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "name": "json", + "visible": true + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 113, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "interactive": true, + "name": "button", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 114, + "type": "textbox", + "props": { + "lines": 1, + "max_lines": 20, + "value": "", + "type": "text", + "autofocus": false, + "show_copy_button": false, + "container": true, + "rtl": false, + "show_label": true, + "min_width": 160, + "name": "textbox", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 115, + "type": "form", + "props": { + "type": "form", + "scale": 0, + "min_width": 0, + "visible": true + } + }, + { + "id": 116, + "type": "form", + "props": { + "type": "form", + "scale": 0, + "min_width": 0, + "visible": true + } + } + ], + "css": null, + "title": "Gradio", + "space_id": null, + "enable_queue": null, + "show_error": true, + "show_api": true, + "is_colab": false, + "stylesheets": [ + "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", + "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" + ], + "theme": "default", + "layout": { + "id": 100, + "children": [ + { + "id": 101 + }, + { + "id": 115, + "children": [ + { + "id": 102 + } + ] + }, + { + "id": 103, + "children": [ + { + "id": 104, + "children": [ + { + "id": 105, + "children": [ + { + "id": 106 + }, + { + "id": 107 + } + ] + }, + { + "id": 108 + } + ] + }, + { + "id": 109, + "children": [ + { + "id": 110, + "children": [ + { + "id": 111 + }, + { + "id": 112 + } + ] + }, + { + "id": 113 + } + ] + } + ] + }, + { + "id": 116, + "children": [ + { + "id": 114 + } + ] + } + ] + }, + "dependencies": [ + { + "targets": [108], + "trigger": "click", + "inputs": [102, 106], + "outputs": [107], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [113], + "trigger": "click", + "inputs": [102, 111], + "outputs": [112], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + } + ] +} diff --git a/test/test_files/xray_config_wrong.json b/test/test_files/xray_config_wrong.json index 149e1990af5a..4d2377374f64 100644 --- a/test/test_files/xray_config_wrong.json +++ b/test/test_files/xray_config_wrong.json @@ -1,548 +1,519 @@ { - "version": "3.40.1", - "mode": "blocks", - "dev_mode": true, - "analytics_enabled": true, - "components": [ - { - "id": 1, - "type": "markdown", - "props": { - "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", - "rtl": false, - "latex_delimiters": [ - { - "left": "$", - "right": "$", - "display": false - } - ], - "name": "markdown", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 2, - "type": "checkboxgroup", - "props": { - "choices": [ - [ - "Covid", - "Covid" - ], - [ - "Malaria", - "Malaria" - ], - [ - "Lung Cancer", - "Lung Cancer" - ] - ], - "value": [], - "label": "Disease to Scan For", - "show_label": true, - "container": true, - "min_width": 160, - "name": "checkboxgroup", - "visible": true - }, - "serializer": "ListStringSerializable", - "api_info": { - "info": { - "type": "array", - "items": { - "type": "string" - } - }, - "serialized_info": false - }, - "example_inputs": { - "raw": [ - "Covid" - ], - "serialized": [ - "Covid" - ] - } - }, - { - "id": 3, - "type": "tabs", - "props": { - "visible": true - } - }, - { - "id": 4, - "type": "tabitem", - "props": { - "label": "X-ray", - "visible": true - } - }, - { - "id": 5, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 6, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 7, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 8, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 9, - "type": "tabitem", - "props": { - "label": "CT Scan", - "visible": true - } - }, - { - "id": 10, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 11, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 12, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 13, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 14, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "", - "type": "text", - "autofocus": false, - "show_copy_button": false, - "container": true, - "rtl": false, - "show_label": true, - "min_width": 160, - "name": "textbox", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 15, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - }, - { - "id": 16, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - }, - { - "id": 118, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "", - "type": "text", - "autofocus": false, - "show_copy_button": false, - "container": true, - "rtl": false, - "show_label": true, - "min_width": 160, - "name": "textbox", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 119, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - } - ], - "css": null, - "title": "Gradio", - "space_id": null, - "enable_queue": null, - "show_error": true, - "show_api": true, - "is_colab": false, - "stylesheets": [ - "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", - "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" - ], - "theme": "default", - "layout": { - "id": 117, - "children": [ - { - "id": 1 - }, - { - "id": 15, - "children": [ - { - "id": 2 - } - ] - }, - { - "id": 3, - "children": [ - { - "id": 4, - "children": [ - { - "id": 5, - "children": [ - { - "id": 6 - }, - { - "id": 7 - } - ] - }, - { - "id": 8 - } - ] - }, - { - "id": 9, - "children": [ - { - "id": 10, - "children": [ - { - "id": 11 - }, - { - "id": 12 - } - ] - }, - { - "id": 13 - } - ] - } - ] - }, - { - "id": 16, - "children": [ - { - "id": 14 - } - ] - }, - { - "id": 119, - "children": [ - { - "id": 118 - } - ] - } - ] - }, - "dependencies": [ - { - "targets": [ - 8 - ], - "trigger": "click", - "inputs": [ - 2, - 6 - ], - "outputs": [ - 7 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - }, - { - "targets": [ - 13 - ], - "trigger": "click", - "inputs": [ - 2, - 11 - ], - "outputs": [ - 12 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - }, - { - "targets": [], - "trigger": "load", - "inputs": [], - "outputs": [ - 118 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - } - ] -} \ No newline at end of file + "version": "3.40.1", + "mode": "blocks", + "dev_mode": true, + "analytics_enabled": true, + "components": [ + { + "id": 1, + "type": "markdown", + "props": { + "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", + "rtl": false, + "latex_delimiters": [ + { + "left": "$", + "right": "$", + "display": false + } + ], + "name": "markdown", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 2, + "type": "checkboxgroup", + "props": { + "choices": [ + ["Covid", "Covid"], + ["Malaria", "Malaria"], + ["Lung Cancer", "Lung Cancer"] + ], + "value": [], + "label": "Disease to Scan For", + "show_label": true, + "container": true, + "min_width": 160, + "name": "checkboxgroup", + "visible": true + }, + "serializer": "ListStringSerializable", + "api_info": { + "info": { + "type": "array", + "items": { + "type": "string" + } + }, + "serialized_info": false + }, + "example_inputs": { + "raw": ["Covid"], + "serialized": ["Covid"] + } + }, + { + "id": 3, + "type": "tabs", + "props": { + "visible": true + } + }, + { + "id": 4, + "type": "tabitem", + "props": { + "label": "X-ray", + "visible": true + } + }, + { + "id": 5, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": true, + "visible": true + } + }, + { + "id": 6, + "type": "image", + "props": { + "image_mode": "RGB", + "source": "upload", + "tool": "editor", + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "selectable": false, + "show_share_button": false, + "show_download_button": true, + "show_label": true, + "container": true, + "min_width": 160, + "name": "image", + "visible": true + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 7, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "name": "json", + "visible": true + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 8, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "interactive": true, + "name": "button", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 9, + "type": "tabitem", + "props": { + "label": "CT Scan", + "visible": true + } + }, + { + "id": 10, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": true, + "visible": true + } + }, + { + "id": 11, + "type": "image", + "props": { + "image_mode": "RGB", + "source": "upload", + "tool": "editor", + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "selectable": false, + "show_share_button": false, + "show_download_button": true, + "show_label": true, + "container": true, + "min_width": 160, + "name": "image", + "visible": true + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 12, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "name": "json", + "visible": true + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 13, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "interactive": true, + "name": "button", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 14, + "type": "textbox", + "props": { + "lines": 1, + "max_lines": 20, + "value": "", + "type": "text", + "autofocus": false, + "show_copy_button": false, + "container": true, + "rtl": false, + "show_label": true, + "min_width": 160, + "name": "textbox", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 15, + "type": "form", + "props": { + "type": "form", + "scale": 0, + "min_width": 0, + "visible": true + } + }, + { + "id": 16, + "type": "form", + "props": { + "type": "form", + "scale": 0, + "min_width": 0, + "visible": true + } + }, + { + "id": 118, + "type": "textbox", + "props": { + "lines": 1, + "max_lines": 20, + "value": "", + "type": "text", + "autofocus": false, + "show_copy_button": false, + "container": true, + "rtl": false, + "show_label": true, + "min_width": 160, + "name": "textbox", + "visible": true + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 119, + "type": "form", + "props": { + "type": "form", + "scale": 0, + "min_width": 0, + "visible": true + } + } + ], + "css": null, + "title": "Gradio", + "space_id": null, + "enable_queue": null, + "show_error": true, + "show_api": true, + "is_colab": false, + "stylesheets": [ + "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", + "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" + ], + "theme": "default", + "layout": { + "id": 117, + "children": [ + { + "id": 1 + }, + { + "id": 15, + "children": [ + { + "id": 2 + } + ] + }, + { + "id": 3, + "children": [ + { + "id": 4, + "children": [ + { + "id": 5, + "children": [ + { + "id": 6 + }, + { + "id": 7 + } + ] + }, + { + "id": 8 + } + ] + }, + { + "id": 9, + "children": [ + { + "id": 10, + "children": [ + { + "id": 11 + }, + { + "id": 12 + } + ] + }, + { + "id": 13 + } + ] + } + ] + }, + { + "id": 16, + "children": [ + { + "id": 14 + } + ] + }, + { + "id": 119, + "children": [ + { + "id": 118 + } + ] + } + ] + }, + "dependencies": [ + { + "targets": [8], + "trigger": "click", + "inputs": [2, 6], + "outputs": [7], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [13], + "trigger": "click", + "inputs": [2, 11], + "outputs": [12], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [], + "trigger": "load", + "inputs": [], + "outputs": [118], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + } + ] +}