mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-12 12:40:29 +08:00
Add Playground to Lite Custom Element (#7660)
* lite playground changes * add changeset * formatting * index * fix tests * fixes * add changeset * styling changes * code parsing * formatting * remove tailiwnd * add shortcut * formatting * linting * formatting * snake case * typing * try fix * remove import --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Hannah <hannahblair@users.noreply.github.com>
This commit is contained in:
parent
abb3f3c116
commit
f739bef6c7
8
.changeset/five-ties-clean.md
Normal file
8
.changeset/five-ties-clean.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
"@gradio/app": minor
|
||||
"@gradio/lite": minor
|
||||
"@gradio/wasm": minor
|
||||
"gradio": minor
|
||||
---
|
||||
|
||||
feat:Add Playground to Lite Custom Element
|
2
js/app/src/images/lightning.svg
Normal file
2
js/app/src/images/lightning.svg
Normal file
@ -0,0 +1,2 @@
|
||||
<!-- Lightning https://iconscout.com/icons/lightning by IconLauk https://iconscout.com/contributors/icon-lauk on IconScout https://iconscout.com" -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 32 32" viewBox="0 0 32 32" id="lightning"><path fill="#999b9e" d="M26.9,10.5C26.7,10.2,26.4,10,26,10h-9V2c0-0.4-0.3-0.8-0.7-1c-0.4-0.1-0.9,0-1.1,0.4l-10,14c-0.2,0.3-0.3,0.7-0.1,1 C5.3,16.8,5.6,17,6,17h8.8L13,29.9c-0.1,0.5,0.2,0.9,0.6,1.1c0.1,0,0.2,0.1,0.3,0.1c0.3,0,0.7-0.2,0.8-0.5l12-19 C27,11.2,27,10.8,26.9,10.5z"/></svg>
|
After Width: | Height: | Size: 545 B |
2
js/app/src/images/play.svg
Normal file
2
js/app/src/images/play.svg
Normal file
@ -0,0 +1,2 @@
|
||||
<!-- Play https://iconscout.com/icons/play by Alexandru Stoica https://iconscout.com/contributors/alexandru-stoica on IconScout https://iconscout.com" -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="6" height="7" viewBox="0 0 6 7" id="play"><g fill="#999b9e" transform="translate(-347 -3766)"><g transform="translate(56 160)"><path d="M296.495 3608.573l-3.994-2.43c-.669-.408-1.501.107-1.501.926v4.862c0 .82.832 1.333 1.5.927l3.995-2.43c.673-.41.673-1.445 0-1.855"/></g></g></svg>
|
After Width: | Height: | Size: 483 B |
354
js/app/src/lite/Playground.svelte
Normal file
354
js/app/src/lite/Playground.svelte
Normal file
@ -0,0 +1,354 @@
|
||||
<script lang="ts">
|
||||
import Index from "../Index.svelte";
|
||||
import type { ThemeMode } from "../types";
|
||||
import { mount_css as default_mount_css } from "../css";
|
||||
import type { api_factory } from "@gradio/client";
|
||||
import type { WorkerProxy } from "@gradio/wasm";
|
||||
import { SvelteComponent, createEventDispatcher } from "svelte";
|
||||
import Code from "@gradio/code";
|
||||
import ErrorDisplay from "./ErrorDisplay.svelte";
|
||||
import lightning from "../images/lightning.svg";
|
||||
import play from "../images/play.svg";
|
||||
import type { LoadingStatus } from "js/statustracker";
|
||||
|
||||
export let autoscroll: boolean;
|
||||
export let version: string;
|
||||
export let initial_height: string;
|
||||
export let app_mode: boolean;
|
||||
export let is_embed: boolean;
|
||||
export let theme_mode: ThemeMode | null = "system";
|
||||
export let control_page_title: boolean;
|
||||
export let container: boolean;
|
||||
export let info: boolean;
|
||||
export let eager: boolean;
|
||||
export let mount_css: typeof default_mount_css = default_mount_css;
|
||||
export let client: ReturnType<typeof api_factory>["client"];
|
||||
export let upload_files: ReturnType<typeof api_factory>["upload_files"];
|
||||
export let worker_proxy: WorkerProxy | undefined = undefined;
|
||||
export let fetch_implementation: typeof fetch = fetch;
|
||||
export let EventSource_factory: (url: URL) => EventSource = (url) =>
|
||||
new EventSource(url);
|
||||
export let space: string | null;
|
||||
export let host: string | null;
|
||||
export let src: string | null;
|
||||
|
||||
export let code: string | undefined;
|
||||
export let error_display: SvelteComponent | null;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let dummy_elem: any = { classList: { contains: () => false } };
|
||||
let dummy_gradio: any = { dispatch: (_: any) => {} };
|
||||
let dummy_loading_status: LoadingStatus = {
|
||||
eta: 0,
|
||||
queue_position: 0,
|
||||
queue_size: 0,
|
||||
status: "complete",
|
||||
show_progress: "hidden",
|
||||
scroll_to_output: false,
|
||||
visible: false,
|
||||
fn_index: 0
|
||||
};
|
||||
|
||||
let loading_text = "";
|
||||
export let loaded = false;
|
||||
worker_proxy?.addEventListener("progress-update", (event) => {
|
||||
loading_text = (event as CustomEvent).detail + "...";
|
||||
});
|
||||
worker_proxy?.addEventListener("initialization-completed", (_) => {
|
||||
loaded = true;
|
||||
});
|
||||
|
||||
function shortcut_run(e: KeyboardEvent): void {
|
||||
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault();
|
||||
dispatch("code", { code });
|
||||
}
|
||||
}
|
||||
|
||||
$: loading_text;
|
||||
$: loaded;
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={shortcut_run} />
|
||||
|
||||
<div class="parent-container">
|
||||
<div class="child-container">
|
||||
<div class:code-editor-border={loaded} class="code-editor">
|
||||
<div class="loading-panel">
|
||||
<div class="code-header">app.py</div>
|
||||
{#if !loaded}
|
||||
<div style="display: flex;"></div>
|
||||
<div class="loading-section">
|
||||
<div class="loading-dot"></div>
|
||||
{loading_text}
|
||||
</div>
|
||||
{:else}
|
||||
<div style="display: flex;"></div>
|
||||
<div class="loading-section">
|
||||
<img src={lightning} alt="lightning icon" class="lightning-logo" />
|
||||
Interactive
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div style="flex-grow: 1;">
|
||||
{#if loaded}
|
||||
<Code
|
||||
bind:value={code}
|
||||
label=""
|
||||
language="python"
|
||||
target={dummy_elem}
|
||||
gradio={dummy_gradio}
|
||||
lines={10}
|
||||
interactive={true}
|
||||
loading_status={dummy_loading_status}
|
||||
/>
|
||||
{:else}
|
||||
<Code
|
||||
bind:value={code}
|
||||
label=""
|
||||
language="python"
|
||||
target={dummy_elem}
|
||||
gradio={dummy_gradio}
|
||||
lines={10}
|
||||
interactive={false}
|
||||
loading_status={dummy_loading_status}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if loaded}
|
||||
<div class="preview">
|
||||
<div class="buttons">
|
||||
<div class="run">
|
||||
<button
|
||||
class="button"
|
||||
on:click={() => {
|
||||
dispatch("code", { code });
|
||||
}}
|
||||
>
|
||||
Run
|
||||
<img src={play} alt="play icon" class="play-logo" />
|
||||
</button>
|
||||
<div class="shortcut">⌘+↵</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; float: right;"></div>
|
||||
</div>
|
||||
<div>
|
||||
{#if !error_display}
|
||||
<Index
|
||||
{autoscroll}
|
||||
{version}
|
||||
{initial_height}
|
||||
{app_mode}
|
||||
{is_embed}
|
||||
{theme_mode}
|
||||
{control_page_title}
|
||||
{container}
|
||||
{info}
|
||||
{eager}
|
||||
{mount_css}
|
||||
{client}
|
||||
{upload_files}
|
||||
bind:worker_proxy
|
||||
{fetch_implementation}
|
||||
{EventSource_factory}
|
||||
{space}
|
||||
{host}
|
||||
{src}
|
||||
/>
|
||||
{:else}
|
||||
<ErrorDisplay
|
||||
is_embed={error_display.is_embed}
|
||||
error={error_display.error}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.parent-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.child-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid rgb(229 231 235);
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.child-container {
|
||||
flex-direction: row;
|
||||
}
|
||||
.code-editor-border {
|
||||
border-right: 1px solid rgb(229 231 235);
|
||||
}
|
||||
}
|
||||
|
||||
.code-editor {
|
||||
flex-grow: 1;
|
||||
flex: 1 1 0%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loading-panel {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
vertical-align: middle;
|
||||
height: 2rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
border-bottom: 1px solid rgb(229 231 235);
|
||||
}
|
||||
|
||||
.code-header {
|
||||
padding-top: 0.25rem;
|
||||
flex-grow: 1;
|
||||
font-family: monospace;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.loading-section {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-left: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
color: #999b9e;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.lightning-logo {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin: 0.125rem;
|
||||
}
|
||||
|
||||
.preview {
|
||||
flex: 1 1 0%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: middle;
|
||||
height: 2rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
border-bottom: 1px solid rgb(229 231 235);
|
||||
}
|
||||
|
||||
.run {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #999b9e;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.25rem;
|
||||
border-radius: 0.375rem;
|
||||
float: right;
|
||||
margin: 0.25rem;
|
||||
color: rgb(107 114 128);
|
||||
background: #eff1f3;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
cursor: pointer;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.play-logo {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
margin: 0.125rem;
|
||||
}
|
||||
|
||||
:global(div.code-editor div.block) {
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
:global(div.code-editor div.block .cm-gutters) {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
:global(div.code-editor div.block .cm-content) {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
:global(div.lite-demo div.gradio-container) {
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
:global(.gradio-container) {
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
.code-editor :global(label) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.code-editor :global(.codemirror-wrappper) {
|
||||
border-radius: var(--block-radius);
|
||||
}
|
||||
|
||||
.code-editor :global(> .block) {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.code-editor :global(.cm-scroller) {
|
||||
height: 100% !important;
|
||||
}
|
||||
:global(.code-editor .block) {
|
||||
border-style: none !important;
|
||||
height: 100%;
|
||||
}
|
||||
:global(.code-editor .container) {
|
||||
display: none;
|
||||
}
|
||||
:global(.code-editor button) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loading-dot {
|
||||
position: relative;
|
||||
left: -9999px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: #fd7b00;
|
||||
color: #fd7b00;
|
||||
box-shadow: 9999px 0 0 -1px;
|
||||
animation: loading-dot 2s infinite linear;
|
||||
animation-delay: 0.25s;
|
||||
margin-left: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
@keyframes loading-dot {
|
||||
0% {
|
||||
box-shadow: 9999px 0 0 -1px;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 9999px 0 0 2px;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 9999px 0 0 -1px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -62,6 +62,7 @@ export function bootstrap_custom_element(
|
||||
requirements: gradioLiteAppOptions.requirements,
|
||||
files: gradioLiteAppOptions.files,
|
||||
entrypoint: gradioLiteAppOptions.entrypoint,
|
||||
playground: this.hasAttribute("playground"),
|
||||
...gradioComponentOptions
|
||||
});
|
||||
});
|
||||
@ -174,7 +175,6 @@ export function bootstrap_custom_element(
|
||||
const firstRequirementsElement = requirementsElements[0];
|
||||
const requirementsTxt = firstRequirementsElement?.textContent ?? "";
|
||||
options.requirements = parseRequirementsTxt(requirementsTxt);
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,8 @@ def hi(name):
|
||||
themeMode: null,
|
||||
autoScroll: false,
|
||||
controlPageTitle: false,
|
||||
appMode: true
|
||||
appMode: true,
|
||||
playground: false
|
||||
});
|
||||
});
|
||||
onDestroy(() => {
|
||||
|
@ -10,6 +10,7 @@ import { wasm_proxied_EventSource_factory } from "./sse";
|
||||
import { wasm_proxied_mount_css, mount_prebuilt_css } from "./css";
|
||||
import type { mount_css } from "../css";
|
||||
import Index from "../Index.svelte";
|
||||
import Playground from "./Playground.svelte";
|
||||
import ErrorDisplay from "./ErrorDisplay.svelte";
|
||||
import type { ThemeMode } from "../types";
|
||||
import { bootstrap_custom_element } from "./custom-element";
|
||||
@ -65,6 +66,7 @@ export interface Options {
|
||||
autoScroll: boolean;
|
||||
controlPageTitle: boolean;
|
||||
appMode: boolean;
|
||||
playground: boolean | undefined;
|
||||
}
|
||||
export function create(options: Options): GradioAppController {
|
||||
// TODO: Runtime type validation for options.
|
||||
@ -87,6 +89,28 @@ export function create(options: Options): GradioAppController {
|
||||
showError((event as CustomEvent).detail);
|
||||
});
|
||||
|
||||
function clean_indent(code: string): string {
|
||||
const lines = code.split("\n");
|
||||
let min_indent: any = null;
|
||||
lines.forEach((line) => {
|
||||
const current_indent = line.match(/^(\s*)\S/);
|
||||
if (current_indent) {
|
||||
const indent_length = current_indent[1].length;
|
||||
min_indent =
|
||||
min_indent !== null
|
||||
? Math.min(min_indent, indent_length)
|
||||
: indent_length;
|
||||
}
|
||||
});
|
||||
if (min_indent === null || min_indent === 0) {
|
||||
return code.trim();
|
||||
}
|
||||
const normalized_lines = lines.map((line) => line.substring(min_indent));
|
||||
return normalized_lines.join("\n").trim();
|
||||
}
|
||||
|
||||
options.code = options.code ? clean_indent(options.code) : options.code;
|
||||
|
||||
// Internally, the execution of `runPythonCode()` or `runPythonFile()` is queued
|
||||
// and its promise will be resolved after the Pyodide is loaded and the worker initialization is done
|
||||
// (see the await in the `onmessage` callback in the webworker code)
|
||||
@ -116,55 +140,109 @@ export function create(options: Options): GradioAppController {
|
||||
};
|
||||
|
||||
let app: SvelteComponent;
|
||||
let app_props: any;
|
||||
|
||||
let loaded = false;
|
||||
|
||||
function showError(error: Error): void {
|
||||
if (app != null) {
|
||||
app.$destroy();
|
||||
}
|
||||
|
||||
app = new ErrorDisplay({
|
||||
target: options.target,
|
||||
props: {
|
||||
is_embed: !options.isEmbed,
|
||||
error
|
||||
}
|
||||
});
|
||||
if (options.playground) {
|
||||
app = new Playground({
|
||||
target: options.target,
|
||||
props: {
|
||||
...app_props,
|
||||
code: options.code,
|
||||
error_display: {
|
||||
is_embed: !options.isEmbed,
|
||||
error
|
||||
},
|
||||
loaded: true
|
||||
}
|
||||
});
|
||||
app.$on("code", (code) => {
|
||||
options.code = clean_indent(code.detail.code);
|
||||
loaded = true;
|
||||
worker_proxy
|
||||
.runPythonCode(options.code)
|
||||
.then(launchNewApp)
|
||||
.catch((e) => {
|
||||
showError(e);
|
||||
throw e;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
app = new ErrorDisplay({
|
||||
target: options.target,
|
||||
props: {
|
||||
is_embed: !options.isEmbed,
|
||||
error
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function launchNewApp(): Promise<void> {
|
||||
if (app != null) {
|
||||
app.$destroy();
|
||||
}
|
||||
|
||||
app = new Index({
|
||||
target: options.target,
|
||||
props: {
|
||||
// embed source
|
||||
space: null,
|
||||
src: null,
|
||||
host: null,
|
||||
// embed info
|
||||
info: options.info,
|
||||
container: options.container,
|
||||
is_embed: options.isEmbed,
|
||||
initial_height: options.initialHeight ?? "300px", // default: 300px
|
||||
eager: options.eager,
|
||||
// gradio meta info
|
||||
version: GRADIO_VERSION,
|
||||
theme_mode: options.themeMode,
|
||||
// misc global behaviour
|
||||
autoscroll: options.autoScroll,
|
||||
control_page_title: options.controlPageTitle,
|
||||
// for gradio docs
|
||||
// TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds
|
||||
app_mode: options.appMode,
|
||||
// For Wasm mode
|
||||
worker_proxy,
|
||||
client,
|
||||
upload_files,
|
||||
mount_css: overridden_mount_css,
|
||||
fetch_implementation: overridden_fetch,
|
||||
EventSource_factory
|
||||
}
|
||||
});
|
||||
app_props = {
|
||||
// embed source
|
||||
space: null,
|
||||
src: null,
|
||||
host: null,
|
||||
// embed info
|
||||
info: options.info,
|
||||
container: options.container,
|
||||
is_embed: options.isEmbed,
|
||||
initial_height: options.initialHeight ?? "300px", // default: 300px
|
||||
eager: options.eager,
|
||||
// gradio meta info
|
||||
version: GRADIO_VERSION,
|
||||
theme_mode: options.themeMode,
|
||||
// misc global behaviour
|
||||
autoscroll: options.autoScroll,
|
||||
control_page_title: options.controlPageTitle,
|
||||
// for gradio docs
|
||||
// TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds
|
||||
app_mode: options.appMode,
|
||||
// For Wasm mode
|
||||
worker_proxy,
|
||||
client,
|
||||
upload_files,
|
||||
mount_css: overridden_mount_css,
|
||||
fetch_implementation: overridden_fetch,
|
||||
EventSource_factory
|
||||
};
|
||||
|
||||
if (options.playground) {
|
||||
app = new Playground({
|
||||
target: options.target,
|
||||
props: {
|
||||
...app_props,
|
||||
code: options.code,
|
||||
error_display: null,
|
||||
loaded: loaded
|
||||
}
|
||||
});
|
||||
app.$on("code", (code) => {
|
||||
options.code = clean_indent(code.detail.code);
|
||||
loaded = true;
|
||||
worker_proxy
|
||||
.runPythonCode(options.code)
|
||||
.then(launchNewApp)
|
||||
.catch((e) => {
|
||||
showError(e);
|
||||
throw e;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
app = new Index({
|
||||
target: options.target,
|
||||
props: app_props
|
||||
});
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
app.$on("loaded", () => {
|
||||
@ -177,6 +255,7 @@ export function create(options: Options): GradioAppController {
|
||||
|
||||
return {
|
||||
run_code: (code: string) => {
|
||||
code = clean_indent(code);
|
||||
return worker_proxy
|
||||
.runPythonCode(code)
|
||||
.then(launchNewApp)
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!doctype html>
|
||||
<!-- A demo HTML file to test the bundled JS and CSS files -->
|
||||
<html style="margin: 0; padding: 0; height: 100%">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
@ -14,36 +14,109 @@
|
||||
href="https://fonts.gstatic.com"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
|
||||
<script type="module" crossorigin src="./dist/lite.js"></script>
|
||||
<link rel="stylesheet" href="./dist/lite.css" />
|
||||
</head>
|
||||
|
||||
<body style="margin: 0; padding: 0; height: 100%">
|
||||
<div id="gradio-app"></div>
|
||||
<body style="padding: 10px; height: 100%; width: 100%">
|
||||
<h1>Lorem Ipsum Dolor</h1>
|
||||
|
||||
<script type="module">
|
||||
// type="module" is necessary to use `createGradioApp()`, which is loaded with <script type="module" /> tag above.
|
||||
createGradioApp({
|
||||
target: document.getElementById("gradio-app"),
|
||||
code: `
|
||||
import gradio as gr
|
||||
<p>
|
||||
<strong>Lorem ipsum</strong> dolor sit amet, consectetur adipiscing elit.
|
||||
Nullam vitae est maximus,
|
||||
<a href="https://example.com">link to example</a>, vestibulum lorem quis,
|
||||
vehicula nunc.
|
||||
</p>
|
||||
|
||||
def greet(name):
|
||||
return "Hello, " + name + "!"
|
||||
<h2>Subheading: Curabitur blandit</h2>
|
||||
|
||||
gr.Interface(fn=greet, inputs="text", outputs="text").launch()
|
||||
`,
|
||||
info: true,
|
||||
container: true,
|
||||
isEmbed: false,
|
||||
initialHeight: "300px",
|
||||
eager: false,
|
||||
themeMode: null,
|
||||
autoScroll: false,
|
||||
controlPageTitle: false,
|
||||
appMode: true
|
||||
});
|
||||
</script>
|
||||
<p>
|
||||
Curabitur blandit tempus porttitor.
|
||||
<em>Etiam porta sem malesuada</em> magna mollis euismod. Donec ullamcorper
|
||||
nulla non metus auctor fringilla.
|
||||
</p>
|
||||
|
||||
<h3>Subsection: Vestibulum</h3>
|
||||
|
||||
<p>
|
||||
Vestibulum id ligula porta felis euismod semper. Sed posuere consectetur
|
||||
est at lobortis.
|
||||
</p>
|
||||
|
||||
<blockquote>Cras mattis consectetur purus sit amet fermentum.</blockquote>
|
||||
|
||||
<pre><code>// Sample code block
|
||||
function helloWorld() {
|
||||
console.log("Hello, world!");
|
||||
}
|
||||
helloWorld();
|
||||
</code></pre>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
|
||||
</li>
|
||||
<li>
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>Bolded text:</b> Duis mollis, est non commodo luctus, nisi erat
|
||||
porttitor ligula, eget lacinia odio sem nec elit.
|
||||
</p>
|
||||
|
||||
<h4>Further Information</h4>
|
||||
|
||||
<p>
|
||||
For more details, visit
|
||||
<a href="https://example.com/moreinfo">our information page</a>.
|
||||
</p>
|
||||
|
||||
<gradio-lite playground>
|
||||
import gradio as gr gr.Interface(fn=lambda x: x, inputs=gr.Textbox(),
|
||||
outputs=gr.Textbox()).launch()
|
||||
</gradio-lite>
|
||||
|
||||
<h3>Subsection: Vestibulum</h3>
|
||||
|
||||
<p>
|
||||
Vestibulum id ligula porta felis euismod semper. Sed posuere consectetur
|
||||
est at lobortis.
|
||||
</p>
|
||||
|
||||
<blockquote>Cras mattis consectetur purus sit amet fermentum.</blockquote>
|
||||
|
||||
<pre><code>// Sample code block
|
||||
function helloWorld() {
|
||||
console.log("Hello, world!");
|
||||
}
|
||||
helloWorld();
|
||||
</code></pre>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
|
||||
</li>
|
||||
<li>
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>Bolded text:</b> Duis mollis, est non commodo luctus, nisi erat
|
||||
porttitor ligula, eget lacinia odio sem nec elit.
|
||||
</p>
|
||||
|
||||
<h4>Further Information</h4>
|
||||
|
||||
<p>
|
||||
For more details, visit
|
||||
<a href="https://example.com/moreinfo">our information page</a>.
|
||||
</p>
|
||||
|
||||
<gradio-lite playground>
|
||||
import gradio as gr gr.ChatInterface(lambda x,y:x).launch()
|
||||
</gradio-lite>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -223,6 +223,7 @@ async function initializeApp(
|
||||
updateProgress("Installing packages");
|
||||
await micropip.install.callKwargs(options.requirements, { keep_going: true });
|
||||
console.debug("Packages are installed.");
|
||||
updateProgress("App is now loaded");
|
||||
}
|
||||
|
||||
const ctx = self as DedicatedWorkerGlobalScope | SharedWorkerGlobalScope;
|
||||
|
@ -92,7 +92,11 @@ export class WorkerProxy extends EventTarget {
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
console.debug("WorkerProxy.constructor(): App initialization is done.");
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("initialization-completed", {
|
||||
detail: null
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(
|
||||
|
Loading…
x
Reference in New Issue
Block a user