Adds copy buttons to website, and better descriptions to API Docs (#5721)

* add missing docstring to highlightedtext

* add description to return types in api_docs

* add copy buttons to docs

* fix up descriptions for filepaths

* add copy buttons to every codeblock

* add changeset

* fix backend tests

* add changeset

* better worded descriptions

* fix color_map description

* fix formatting in code snippets

* add space

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Ali Abdalla 2023-09-27 23:23:01 -07:00 committed by GitHub
parent e3e47991ac
commit 84e03fe506
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 146 additions and 165 deletions

View File

@ -0,0 +1,8 @@
---
"@gradio/app": patch
"gradio": patch
"gradio_client": patch
"website": patch
---
feat:Adds copy buttons to website, and better descriptions to API Docs

View File

@ -152,7 +152,10 @@ class ImgSerializable(Serializable):
"""Expects a base64 string as input/output which is serialized to a filepath."""
def serialized_info(self):
return {"type": "string", "description": "filepath or URL to image"}
return {
"type": "string",
"description": "filepath on your computer (or URL) of image",
}
def api_info(self) -> dict[str, bool | dict]:
return {"info": serializer_types["ImgSerializable"], "serialized_info": True}
@ -222,13 +225,19 @@ class FileSerializable(Serializable):
}
def _single_file_serialized_info(self):
return {"type": "string", "description": "filepath or URL to file"}
return {
"type": "string",
"description": "filepath on your computer (or URL) of file",
}
def _multiple_file_serialized_info(self):
return {
"type": "array",
"description": "List of filepath(s) or URL(s) to files",
"items": {"type": "string", "description": "filepath or URL to file"},
"items": {
"type": "string",
"description": "filepath on your computer (or URL) of file",
},
}
def _multiple_file_api_info(self):
@ -386,7 +395,10 @@ class FileSerializable(Serializable):
class VideoSerializable(FileSerializable):
def serialized_info(self):
return {"type": "string", "description": "filepath or URL to video file"}
return {
"type": "string",
"description": "filepath on your computer (or URL) of video file",
}
def api_info(self) -> dict[str, dict | bool]:
return {"info": serializer_types["FileSerializable"], "serialized_info": True}

View File

@ -26,7 +26,7 @@
"oneOf": [
{
"type": "string",
"description": "filepath or URL to file"
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",
@ -57,7 +57,7 @@
"anyOf": [
{
"type": "string",
"description": "filepath or URL to file"
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",
@ -91,7 +91,7 @@
"oneOf": [
{
"type": "string",
"description": "filepath or URL to file"
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",
@ -124,7 +124,7 @@
"anyOf": [
{
"type": "string",
"description": "filepath or URL to file"
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",

View File

@ -855,7 +855,7 @@ class TestAPIInfo:
assert inputs[1]["python_type"] == {
"type": "str",
"description": "filepath or URL to file",
"description": "filepath on your computer (or URL) of file",
}
assert isinstance(inputs[1]["example_input"], str)
@ -867,7 +867,7 @@ class TestAPIInfo:
assert outputs[1]["python_type"] == {
"type": "str",
"description": "filepath or URL to file",
"description": "filepath on your computer (or URL) of file",
}
def test_layout_components_in_output(self, hello_world_with_group):

View File

@ -52,6 +52,7 @@ class HighlightedText(Changeable, Selectable, IOComponent, JSONSerializable):
"""
Parameters:
value: Default value to show. If callable, the function will be called whenever the app loads to set the initial value of the component.
color_map: A dictionary mapping labels to colors. The colors may be specified as hex codes or by their names. For example: {"person": "red", "location": "#FFEE22"}
show_legend: whether to show span categories in a separate legend or inline.
combine_adjacent: If True, will merge the labels of adjacent tokens belonging to the same category.
adjacent_separator: Specifies the separator to be used between tokens if combine_adjacent is True.

View File

@ -55,8 +55,8 @@ code[class*="language-"] ::selection {
/* Code blocks */
pre[class*="language-"] {
margin: 0.5em 0;
padding: 1em;
margin: 0;
padding: 0;
overflow: auto;
}

View File

@ -144,7 +144,7 @@ code.language-bash {
/* copy button */
.clipboard-button {
@apply absolute right-0 px-1.5 pt-0.5 pb-1 m-4 text-gray-500 text-sm z-[100] opacity-0 duration-100;
@apply absolute right-0 px-1.5 pb-1 text-gray-500 text-sm z-[100] opacity-0 duration-100;
}
.clipboard-button:hover {
@apply cursor-pointer;
@ -156,7 +156,7 @@ code.language-bash {
@apply outline-0;
}
.codeblock {
@apply relative;
@apply relative bg-gray-50 mx-auto p-3 mt-2;
}
.codeblock:hover > .clipboard-button {
@apply opacity-100 duration-200;

View File

@ -0,0 +1,21 @@
<script lang="ts">
import { svgCopy, svgCheck } from "$lib/assets/copy.js";
export let content: string = ""
let copied = false;
async function copy() {
await navigator.clipboard.writeText(content)
copied = true;
setTimeout(() => (copied = false), 2000);
}
</script>
<button on:click={copy} class="clipboard-button m-2" role="button" tabindex={0}>
{#if !copied}
{@html svgCopy}
{:else}
{@html svgCheck}
{/if}
</button>

View File

@ -1,36 +1,20 @@
<script lang="ts">
import { svgCopy, svgCheck } from "$lib/assets/copy.js";
export let name: string;
export let code: string;
export let highlighted_code: string;
export let on_main: boolean = false;
let copied = false;
function copy(code: string) {
navigator.clipboard.writeText(code);
copied = true;
setTimeout(() => (copied = false), 2000);
}
$: on_main;
</script>
<div class="codeblock bg-gray-50 mx-auto p-3 my-3" id="{name}_code">
<div class="codeblock" id="{name}_code">
<a
class="clipboard-button"
class="clipboard-button m-2"
href="https://colab.research.google.com/github/gradio-app/gradio/blob/main/demo/{name}/run.ipynb"
target="_blank"
style="right:30px"
>
<img src="https://colab.research.google.com/assets/colab-badge.svg" />
</a>
<button class="clipboard-button" type="button" on:click={() => copy(code)}>
{#if !copied}
{@html svgCopy}
{:else}
{@html svgCheck}
{/if}
</button>
<pre class=" max-h-80 overflow-auto"><code class="code language-python"
>{@html highlighted_code}</code
>

View File

@ -50,7 +50,7 @@
>
<div
class:hidden={!code}
class="codeblock rounded-lg bg-gray-50 shadow-inner text-sm md:text-base mx-auto max-w-5xl"
class="codeblock text-sm md:text-base mx-auto max-w-5xl"
>
{@html code}
</div>

View File

@ -2,6 +2,7 @@
export let fn: any;
import anchor from "../assets/img/anchor.svg";
function handleAnchorClick(event: MouseEvent) {
event.preventDefault();
const link = event.currentTarget as HTMLAnchorElement;
@ -30,12 +31,12 @@
</div>
{#if fn.override_signature}
<div class="codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
<pre><code class="code language-python">{fn.override_signature}</code
></pre>
</div>
{:else}
<div class="codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
<pre><code class="code language-python"
>{fn.parent}.<span>{fn.name}&lpar;</span
><!--
@ -78,7 +79,7 @@
><img class="anchor-img-small" src={anchor} /></a
>
</h4>
<div class="mt-2 codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
<pre><code class="code language-python"
>{@html fn.highlighted_example}</code
></pre>

View File

@ -25,6 +25,27 @@
}
import version_json from "$lib/json/version.json";
let version = version_json.version;
import CopyButton from '$lib/components/CopyButton.svelte'
import { afterNavigate } from "$app/navigation";
afterNavigate(() => {
for (const node of document.querySelectorAll('.codeblock')) {
let children = Array.from(node.querySelectorAll('pre, a'));
let textContent = node.textContent;
node.innerHTML = "";
new CopyButton({
target: node,
props: {
content: textContent ?? '',
},
})
for (const child of children) {
node.appendChild(child);
}
}})
</script>
<svelte:head>

View File

@ -7,7 +7,6 @@
import anchor from "$lib/assets/img/anchor.svg";
import { onDestroy } from "svelte";
import { page } from "$app/stores";
import { svgCopy, svgCheck } from "$lib/assets/copy.js";
export let data: any = {};
@ -60,13 +59,6 @@
}
}
let copied = false;
function copy(code: string) {
navigator.clipboard.writeText(code);
copied = true;
setTimeout(() => (copied = false), 2000);
}
$: obj = data.obj;
$: mode = data.mode;
$: on_main = data.on_main;
@ -114,19 +106,14 @@
</div>
{#if on_main}
<div class="codeblock bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<div class="bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<p class="my-2">
To install Gradio from main, run the following command:
</p>
<button class="clipboard-button" type="button" on:click={() => copy("pip install " + wheel)}>
{#if !copied}
{@html svgCopy}
{:else}
{@html svgCheck}
{/if}
</button>
<pre class="language-bash" style="padding-right: 25px;"><code class="language-bash text-xs">pip install {wheel}</code></pre>
<p class="float-right text-sm">
<div class="codeblock">
<pre class="language-bash" style="padding-right: 50px;"><code class="language-bash">pip install {wheel}</code></pre>
</div>
<p class="float-right text-sm">
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
</div>
@ -176,7 +163,7 @@
</h3>
</div>
<div class="codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
{#if obj.override_signature}
<pre><code class="code language-python"
>{obj.override_signature}</code
@ -276,7 +263,7 @@
><img class="anchor-img-small" src={anchor} /></a
>
</h4>
<div class="codeblock bg-gray-50 mx-auto p-3 mt-2">
<div class="codeblock">
<pre><code class="code language-python"
>{@html obj.highlighted_example}</code
></pre>

View File

@ -3,8 +3,6 @@
import MetaTags from "$lib/components/MetaTags.svelte";
import dataflow_svg from "$lib/assets/img/dataflow.svg";
import { page } from "$app/stores";
import { svgCopy, svgCheck } from "$lib/assets/copy.js";
export let data;
@ -19,13 +17,6 @@
let on_main: boolean;
let wheel: string = data.wheel;
let copied = false;
function copy(code: string) {
navigator.clipboard.writeText(code);
copied = true;
setTimeout(() => (copied = false), 2000);
}
$: on_main = data.on_main;
$: components = data.components;
$: helpers = data.helpers;
@ -69,22 +60,17 @@
</div>
{#if on_main}
<div class="codeblock bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<p class="my-2">
To install Gradio from main, run the following command:
</p>
<button class="clipboard-button" type="button" on:click={() => copy("pip install " + wheel)}>
{#if !copied}
{@html svgCopy}
{:else}
{@html svgCheck}
{/if}
</button>
<pre class="language-bash" style="padding-right: 25px;"><code class="language-bash text-xs">pip install {wheel}</code></pre>
<p class="float-right text-sm">
<div class="bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<p class="my-2">
To install Gradio from main, run the following command:
</p>
<div class="codeblock">
<pre class="language-bash" style="padding-right: 50px;"><code class="language-bash">pip install {wheel}</code></pre>
</div>
<p class="float-right text-sm">
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
</div>
</div>
{/if}
<div class="lg:ml-10 flex justify-between mt-4">

View File

@ -6,8 +6,6 @@
import anchor from "$lib/assets/img/anchor.svg";
import { onDestroy } from "svelte";
import { page } from "$app/stores";
import { svgCopy, svgCheck } from "$lib/assets/copy.js";
export let data: any;
@ -57,13 +55,6 @@
let on_main: boolean;
let wheel: string = data.wheel;
let copied = false;
function copy(code: string) {
navigator.clipboard.writeText(code);
copied = true;
setTimeout(() => (copied = false), 2000);
}
$: on_main = data.on_main;
$: components = data.components;
$: helpers = data.helpers;
@ -109,21 +100,16 @@
</div>
{#if on_main}
<div class="codeblock bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<div class="bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<p class="my-2">
To install Gradio from main, run the following command:
</p>
<button class="clipboard-button" type="button" on:click={() => copy("pip install " + wheel)}>
{#if !copied}
{@html svgCopy}
{:else}
{@html svgCheck}
{/if}
</button>
<pre class="language-bash" style="padding-right: 25px;"><code class="language-bash text-xs">pip install {wheel}</code></pre>
<div class="codeblock">
<pre class="language-bash" style="padding-right: 50px;"><code class="language-bash">pip install {wheel}</code></pre>
</div>
<p class="float-right text-sm">
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
</div>
{/if}
@ -194,13 +180,13 @@
</div>
{#if obj.override_signature}
<div class="codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
<pre><code class="code language-python"
>{obj.override_signature}</code
></pre>
</div>
{:else}
<div class="codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
<pre><code class="code language-python"
>{obj.parent}.<span>{obj.name}&lpar;</span
><!--
@ -280,7 +266,7 @@
><img class="anchor-img-small" src={anchor} /></a
>
</h4>
<div class="codeblock bg-gray-50 mx-auto p-3 mt-2">
<div class="codeblock">
<pre><code class="code language-python"
>{@html obj.highlighted_example}</code
></pre>

View File

@ -2,8 +2,6 @@
import DocsNav from "$lib/components/DocsNav.svelte";
import MetaTags from "$lib/components/MetaTags.svelte";
import { page } from "$app/stores";
import { svgCopy, svgCheck } from "$lib/assets/copy.js";
export let data;
let components = data.components;
@ -15,13 +13,6 @@
let on_main: boolean;
let wheel: string = data.wheel;
let copied = false;
function copy(code: string) {
navigator.clipboard.writeText(code);
copied = true;
setTimeout(() => (copied = false), 2000);
}
$: on_main = data.on_main;
$: components = data.components;
$: helpers = data.helpers;
@ -65,21 +56,16 @@
</div>
{#if on_main}
<div class="codeblock bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<div class="bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<p class="my-2">
To install Gradio from main, run the following command:
</p>
<button class="clipboard-button" type="button" on:click={() => copy("pip install " + wheel)}>
{#if !copied}
{@html svgCopy}
{:else}
{@html svgCheck}
{/if}
</button>
<pre class="language-bash" style="padding-right: 25px;"><code class="language-bash text-xs">pip install {wheel}</code></pre>
<div class="codeblock">
<pre class="language-bash" style="padding-right: 50px;"><code class="language-bash">pip install {wheel}</code></pre>
</div>
<p class="float-right text-sm">
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
</div>
{/if}
@ -101,8 +87,8 @@
</div>
</a>
</div>
<div class="flex flex-row mr-28">
<div class="lg:w-3/4 lg:ml-10 lg:mr-24">
<div class="flex flex-row">
<div class="lg:w-full lg:ml-10">
<div class="obj" id="python-client">
<h2
id="python-client-header"
@ -129,7 +115,7 @@
<code class="language-bash">gradio</code>:
</p>
<div class="codeblock bg-gray-50 mx-auto p-3 my-3">
<div class="codeblock">
<pre><code class="language-bash">pip install gradio_client</code
></pre>
</div>

View File

@ -6,8 +6,6 @@
import anchor from "$lib/assets/img/anchor.svg";
import { onDestroy } from "svelte";
import { page } from "$app/stores";
import { svgCopy, svgCheck } from "$lib/assets/copy.js";
export let data: any;
@ -57,13 +55,6 @@
let on_main: boolean;
let wheel: string = data.wheel;
let copied = false;
function copy(code: string) {
navigator.clipboard.writeText(code);
copied = true;
setTimeout(() => (copied = false), 2000);
}
$: on_main = data.on_main;
$: components = data.components;
$: helpers = data.helpers;
@ -109,21 +100,16 @@
</div>
{#if on_main}
<div class="codeblock bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<div class="bg-gray-100 border border-gray-200 text-gray-800 px-3 py-1 mt-4 rounded-lg lg:ml-10">
<p class="my-2">
To install Gradio from main, run the following command:
</p>
<button class="clipboard-button" type="button" on:click={() => copy("pip install " + wheel)}>
{#if !copied}
{@html svgCopy}
{:else}
{@html svgCheck}
{/if}
</button>
<pre class="language-bash" style="padding-right: 25px;"><code class="language-bash text-xs">pip install {wheel}</code></pre>
<div class="codeblock">
<pre class="language-bash" style="padding-right: 50px;"><code class="language-bash">pip install {wheel}</code></pre>
</div>
<p class="float-right text-sm">
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
*Note: Setting <code style="font-size: 0.85rem">share=True</code> in <code style="font-size: 0.85rem">launch()</code> will not work.
</p>
</div>
{/if}
@ -196,13 +182,13 @@
</div>
{#if obj.override_signature}
<div class="codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
<pre><code class="code language-python"
>{obj.override_signature}</code
></pre>
</div>
{:else}
<div class="codeblock bg-gray-50 mx-auto p-3">
<div class="codeblock">
<pre><code class="code language-python"
>{obj.parent}.<span>{obj.name}&lpar;</span
><!--
@ -286,7 +272,7 @@
><img class="anchor-img-small" src={anchor} /></a
>
</h4>
<div class="codeblock bg-gray-50 mx-auto p-3 mt-2">
<div class="codeblock">
<pre><code class="code language-python"
>{@html obj.highlighted_example}</code
></pre>

View File

@ -29,11 +29,11 @@ function highlight(code: string, lang: string | undefined) {
const _lang = langs[lang as keyof typeof langs] || "";
const highlighted = _lang
? `<pre class="language-${lang}"><code>${Prism.highlight(
? `<div class="codeblock"><pre class="language-${lang}"><code>${Prism.highlight(
code,
Prism.languages[_lang],
_lang
)}</code></pre>`
)}</code></pre></div>`
: code;
return highlighted;

View File

@ -53,7 +53,7 @@ client = Client(<span class="token string">"{root}"</span>)
result = client.predict(<!--
-->{#each endpoint_parameters as { label, type, python_type, component, example_input, serializer }, i}<!--
-->
<span
<span
class="example-inputs"
>{represent_value(example_input, python_type.type, "py")}</span
>,<!--
@ -64,19 +64,16 @@ result = client.predict(<!--
-->{/if}<!--
--><span class="desc"
><!--
--> # {python_type.type} {#if python_type.description}({python_type.description})
{/if}<!--
-->in '{label}' <!--
--> # {python_type.type} {#if python_type.description}({python_type.description}){/if}<!----> in '{label}' <!--
-->{component} component<!--
--></span
><!--
-->
{/each}
{#if named}
api_name="/{dependency.api_name}"
{:else}
fn_index={dependency_index}
{/if}
--></span><!--
-->{/each}<!--
-->{#if named}
api_name="/{dependency.api_name}"<!--
-->{:else}
fn_index={dependency_index}
{/if}
)
print(result)</pre>
</div>

View File

@ -22,9 +22,14 @@
<div class:second-level={endpoint_returns.length > 1}>
<span class="desc"
><!--
--> # {#if current_language === "python"}{python_type.type}{:else}{js_returns[
--> # {#if current_language === "python"}{python_type.type}{#if python_type?.description}&nbsp;({python_type.description}){/if}{:else}{js_returns[
i
].type}{/if}
].type}{#if js_returns[
i
].description}&nbsp;({js_returns[
i
]
.description}){/if}{/if}
<!--
-->representing output in '{label}' <!--
-->{component}